Commit Graph

27 Commits

Author SHA1 Message Date
robonen ea96d720f2 perf(primitives): place the select panel in one layout pass
Publish to NPM / Check version changes and publish (push) Successful in 9m38s
`position()` interleaved geometry reads with inline-style writes: the horizontal
branch wrote `minWidth`/`left` and the vertical branch then read `scrollHeight`,
`getComputedStyle`, `offsetHeight` and `offsetTop`, and a second write of
`bottom` was followed by a read of `clientHeight`. Each read after a write
forces a synchronous layout, so a single placement cost at least two — and
placement runs on mount, on resize and while scrolling an expanding panel.

Split it into measure, compute and commit: every read now happens before the
first write, and the result is applied as one object rather than nine separate
property assignments.

The commit also always writes both edges of each axis. A resize can flip the
vertical branch from `bottom` to `top`, and the previous code left the old edge
in place, over-constraining the box.

No behavioural change — the arithmetic is untouched, and the placement tests
pass unchanged.
2026-08-10 04:37:43 +07:00
robonen 6da5ecaa83 fix(primitives): place the select panel when nothing is selected
Publish to NPM / Check version changes and publish (push) Has been cancelled
Item-aligned placement centres the panel on the selected item, and `position()`
returned early unless both the item and its text node were known. The content
already adopts the first valid item as the anchor when the model matches no
option, but only the item is registered — the text node registers solely for the
selected value, so the pair was never complete and the early return fired. The
wrapper is `position: fixed`, so it stayed at the viewport origin: to a user the
dropdown simply does not open.

This is not an edge case. A stale id, a deleted record or a directory that has
not finished loading all leave the model unmatched, and the whole select then
looks broken rather than merely unlabelled.

Recover the text node from the item's own `aria-labelledby` instead of adding a
second registration — writing the anchor refs from inside the item's tracking
effect closes a reactive cycle ("Maximum recursive updates exceeded"). Reset the
text ref alongside the item ref per open cycle so a stale node cannot pair with
a fresh item. Finally, keep the guard from ever stranding the panel again: with
no anchors at all — an empty option list — fall back to a plain trigger-aligned
drop instead of returning with the wrapper unplaced.

Both paths are covered by browser tests that fail on the previous code.
2026-08-10 04:30:24 +07:00
robonen 1d2130f279 fix(primitives): make v-model, native attributes and panel styling usable under strict TS
Publish to NPM / Check version changes and publish (push) Successful in 11m33s
Consuming the package under `verbatimModuleSyntax` + `strictTemplates` surfaced
four defects that forced workarounds downstream.

- Drop the deprecated `SelectValue` string alias. It collided with the
  `SelectValue` component exported from the same barrel, so the component
  resolved to the type meaning and could not be imported (TS1484).

- Narrow the select's model to `SelectModelValue<T, Multiple>` and make
  `TabsRoot` generic over its value, so a plain `v-model` on a `Ref<string>`
  type-checks. Both roots declare the value prop and emit explicitly instead of
  via `defineModel`, which would widen the payload with `| undefined` even
  though neither control ever clears its value.

- Stop declaring `defineModel` keys in `defineEmits` as well. The duplicate
  erased the payload type from the generated declarations, shipping
  `(...args: unknown[]) => any` for eleven components' model events.

- Let every part accept global DOM attributes (`id`, `role`, `aria-*`,
  `data-*`, ...) through `PrimitiveAttributes`. The heritage clause is marked
  `@vue-ignore`, so they stay out of the runtime props and keep falling through
  via `$attrs` exactly as before.

- Give `SelectContent` and `SelectViewport` a single styleable root: the
  content forwards `$attrs` onto the panel, and the viewport's scrollbar CSS
  moves to a reference-counted `<head>` style tag. A forwarded `class` was
  previously dropped, leaving the panel unstyled.

The tsconfig vue preset gains `htmlAttributes: ["aria-*", "data-*"]` so
hyphenated data attributes are not camelized before they reach those types.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 00:14:44 +07:00
robonen e59e05ac05 chore: bump version to 0.0.2 in jsr.json and package.json
Publish to NPM / Check version changes and publish (push) Successful in 9m40s
2026-08-03 21:53:43 +07:00
robonen 85313c6046 feat: update useSnapPoints to improve drawer snapping behavior and add new features
Publish to NPM / Check version changes and publish (push) Successful in 11m14s
2026-08-03 21:12:35 +07:00
robonen c6b6b93e81 chore: update dependencies and package manager versions across projects
Publish to NPM / Check version changes and publish (push) Failing after 10m54s
2026-07-31 04:21:32 +07:00
robonen 655f30a658 test(scroll-area): improve glimpse type test for pointer interactions
Publish to NPM / Check version changes and publish (push) Successful in 11m30s
2026-06-18 03:17:25 +07:00
robonen ab6d8f6ce0 build: bump new versions
Publish to NPM / Check version changes and publish (push) Failing after 10m34s
2026-06-18 02:57:03 +07:00
robonen e73e8d2cdd chore: update dependencies and configurations across multiple packages
Publish to NPM / Check version changes and publish (push) Failing after 10m44s
2026-06-18 02:02:58 +07:00
robonen eefd7abf83 feat(primitives): media-editor components, category reorg, perf + type cleanup
Reorganize components into category folders (forms/canvas/overlays/etc.); add the
media-editor headless family (timeline, curve-editor, waveform, crop, color
picker, etc.); apply perf fixes (O(1) collection lookups, plain-object drag
state, gesture-leak teardown, shallowRef color state, rect caching) and replace
source `any` with proper types.
2026-06-15 16:54:29 +07:00
robonen 661a55719e perf(primitives): add performance audit report and vitest bench baselines
Library-wide Vue+V8 perf/leak audit (PERF_AUDIT.md) plus bench baselines for the
hot-path modules (timeline, curve-editor, spline, pointer-drag, collection, etc.).
2026-06-15 16:54:28 +07:00
robonen a39d93a6a4 Merge branch 'master' into docs 2026-06-10 16:24:41 +07:00
robonen 9375304e1a feat(navigation-menu): enhance context handling and lifecycle management 2026-06-10 16:16:12 +07:00
robonen 98e243dc04 Merge pull request #141 from robonen/docs
feat(forms): add useMaskedField and useMaskedInput composables for in…
2026-06-09 13:58:53 +07:00
robonen 07937e26db feat(forms): add useMaskedField and useMaskedInput composables for input masking 2026-06-09 13:54:52 +07:00
renovate[bot] a0154dabf5 chore(deps): update all non-major dependencies (#120)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-09 01:15:28 +00:00
robonen 73e701a2c5 chore: update all deps 2026-06-08 17:11:14 +07:00
robonen 53f2d7ceef docs: add package introductions and the @robonen/crdt guide
An intro.vue landing for all 12 packages, plus a multi-section crdt guide (Concepts, Primitives, Replication & Sync, and an interactive convergence Playground).
2026-06-08 15:52:03 +07:00
robonen def1db8b6c fix(primitives): component fixes and test cleanup 2026-06-08 15:51:30 +07:00
robonen 626fbc70d8 fix(primitives): eslint/tsconfig migration, asChild refactor, type fixes
- Migrate to eslint flat config + composite tsconfig.
- Complete the asChild→as="template" refactor (remove asChild prop + :as-child
  bindings across components, matching Primitive's slot model).
- Fix test type errors and source type-safety (useGraceArea hull/point math,
  FocusScope/util ref typing).

Note: ~53 vue-tsc errors remain (HTML attr/event passthrough typing on
transparent wrapper components + a couple of duplicate-export naming
collisions) — not gated by CI (build/lint/test green); pending a
component-attribute-typing design decision.
2026-06-07 16:29:56 +07:00
robonen 1d3efa5028 feat(primitives): add menu, dropdown-menu, context-menu, and menubar primitives
Implements WAI-ARIA APG-compliant headless menu primitive families:

- menu: base primitive with MenuRoot, MenuContent, MenuItem,
  MenuCheckboxItem, MenuRadioGroup/Item, MenuSub, and helpers
- dropdown-menu: DropdownMenuRoot with trigger anchoring
- context-menu: ContextMenuRoot with right-click virtual anchor
- menubar: MenubarRoot with keyboard navigation between menus

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-17 18:48:43 +07:00
robonen 333a18cbaf refactor(presence): enhance slot handling and attribute forwarding 2026-03-26 17:19:31 +07:00
robonen 5fa38110b7 feat(vue/primitives): remove execArgv option from test configuration 2026-03-10 18:36:45 +07:00
robonen 4574bae0b6 feat(vue/primitives): add FocusScope component with auto-focus and focus trap functionality 2026-03-10 18:28:52 +07:00
robonen a996eb74b9 feat: update package.json exports to support new module formats and types 2026-03-08 08:19:01 +07:00
robonen bcc9cb2915 feat(vue/primitives): implement pagination components with accessibility and testing 2026-03-08 04:18:10 +07:00
robonen 41d5e18f6b feat(monorepo): migrate vue packages and apply oxlint refactors 2026-03-07 18:07:22 +07:00