@funstack/ui 0.1.0-alpha.5 → 0.1.0-alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/accordion/accordion-item.mjs +2 -2
  2. package/dist/accordion/accordion-panel.mjs +2 -2
  3. package/dist/accordion/accordion-root.mjs +3 -3
  4. package/dist/accordion/accordion-trigger.mjs +2 -2
  5. package/dist/button/button.d.mts +78 -0
  6. package/dist/button/button.d.mts.map +1 -0
  7. package/dist/button/button.mjs +77 -0
  8. package/dist/button/button.mjs.map +1 -0
  9. package/dist/button/index.d.mts +3 -0
  10. package/dist/button/index.mjs +1 -0
  11. package/dist/checkbox/checkbox.mjs +2 -2
  12. package/dist/checkbox-group/checkbox-group-item.mjs +1 -1
  13. package/dist/checkbox-group/checkbox-group-parent.mjs +1 -1
  14. package/dist/checkbox-group/checkbox-group-root.mjs +1 -1
  15. package/dist/combobox/combobox-clear.d.mts +6 -3
  16. package/dist/combobox/combobox-clear.d.mts.map +1 -1
  17. package/dist/combobox/combobox-clear.mjs +10 -5
  18. package/dist/combobox/combobox-clear.mjs.map +1 -1
  19. package/dist/combobox/combobox-group.mjs +1 -1
  20. package/dist/combobox/combobox-list.mjs +1 -1
  21. package/dist/combobox/combobox-option.mjs +1 -1
  22. package/dist/combobox/combobox-popup.mjs +2 -2
  23. package/dist/combobox/combobox-root.mjs +3 -3
  24. package/dist/combobox/combobox-trigger.d.mts +6 -2
  25. package/dist/combobox/combobox-trigger.d.mts.map +1 -1
  26. package/dist/combobox/combobox-trigger.mjs +10 -4
  27. package/dist/combobox/combobox-trigger.mjs.map +1 -1
  28. package/dist/dialog/dialog-close.d.mts +8 -3
  29. package/dist/dialog/dialog-close.d.mts.map +1 -1
  30. package/dist/dialog/dialog-close.mjs +12 -8
  31. package/dist/dialog/dialog-close.mjs.map +1 -1
  32. package/dist/dialog/dialog-form.mjs +1 -1
  33. package/dist/dialog/dialog-popup.mjs +3 -3
  34. package/dist/dialog/dialog-root.mjs +2 -2
  35. package/dist/dialog/dialog-trigger.d.mts +8 -3
  36. package/dist/dialog/dialog-trigger.d.mts.map +1 -1
  37. package/dist/dialog/dialog-trigger.mjs +15 -8
  38. package/dist/dialog/dialog-trigger.mjs.map +1 -1
  39. package/dist/field/field-root.mjs +3 -3
  40. package/dist/form/form-root.mjs +1 -1
  41. package/dist/form/form-submit.d.mts +4 -1
  42. package/dist/form/form-submit.d.mts.map +1 -1
  43. package/dist/form/form-submit.mjs.map +1 -1
  44. package/dist/index.d.mts +3 -2
  45. package/dist/index.mjs +2 -1
  46. package/dist/internal/render-element.mjs +18 -5
  47. package/dist/internal/render-element.mjs.map +1 -1
  48. package/dist/internal/use-action-trigger.mjs +17 -6
  49. package/dist/internal/use-action-trigger.mjs.map +1 -1
  50. package/dist/internal/use-field-control.mjs +1 -1
  51. package/dist/internal/use-popover-root.mjs +1 -1
  52. package/dist/internal/use-popover-trigger.mjs +6 -5
  53. package/dist/internal/use-popover-trigger.mjs.map +1 -1
  54. package/dist/internal/use-render.mjs +2 -2
  55. package/dist/internal/use-render.mjs.map +1 -1
  56. package/dist/menu/menu-checkbox-item.mjs +2 -2
  57. package/dist/menu/menu-dom.mjs +7 -1
  58. package/dist/menu/menu-dom.mjs.map +1 -1
  59. package/dist/menu/menu-group.mjs +1 -1
  60. package/dist/menu/menu-item.d.mts +6 -2
  61. package/dist/menu/menu-item.d.mts.map +1 -1
  62. package/dist/menu/menu-item.mjs +6 -4
  63. package/dist/menu/menu-item.mjs.map +1 -1
  64. package/dist/menu/menu-popup.mjs +1 -1
  65. package/dist/menu/menu-radio-group.mjs +1 -1
  66. package/dist/menu/menu-root.mjs +1 -1
  67. package/dist/menu/menu-submenu-trigger.mjs +1 -1
  68. package/dist/menu/menu-trigger.d.mts +6 -3
  69. package/dist/menu/menu-trigger.d.mts.map +1 -1
  70. package/dist/menu/menu-trigger.mjs +3 -3
  71. package/dist/menu/menu-trigger.mjs.map +1 -1
  72. package/dist/number-field/number-field-decrement.d.mts +4 -3
  73. package/dist/number-field/number-field-decrement.d.mts.map +1 -1
  74. package/dist/number-field/number-field-decrement.mjs +4 -3
  75. package/dist/number-field/number-field-decrement.mjs.map +1 -1
  76. package/dist/number-field/number-field-increment.d.mts +8 -3
  77. package/dist/number-field/number-field-increment.d.mts.map +1 -1
  78. package/dist/number-field/number-field-increment.mjs +9 -6
  79. package/dist/number-field/number-field-increment.mjs.map +1 -1
  80. package/dist/number-field/number-field-input.mjs +1 -1
  81. package/dist/number-field/number-field-root.mjs +5 -5
  82. package/dist/number-field/number-field-root.mjs.map +1 -1
  83. package/dist/number-field/use-step-button.mjs +6 -1
  84. package/dist/number-field/use-step-button.mjs.map +1 -1
  85. package/dist/popover/popover-close.d.mts +9 -3
  86. package/dist/popover/popover-close.d.mts.map +1 -1
  87. package/dist/popover/popover-close.mjs +13 -8
  88. package/dist/popover/popover-close.mjs.map +1 -1
  89. package/dist/popover/popover-popup.mjs +2 -2
  90. package/dist/popover/popover-trigger.d.mts +8 -4
  91. package/dist/popover/popover-trigger.d.mts.map +1 -1
  92. package/dist/popover/popover-trigger.mjs +3 -3
  93. package/dist/popover/popover-trigger.mjs.map +1 -1
  94. package/dist/radio-group/radio-group-item.mjs +1 -1
  95. package/dist/radio-group/radio-group-root.mjs +1 -1
  96. package/dist/select/select-root.mjs +1 -1
  97. package/dist/slider/slider-root.mjs +6 -6
  98. package/dist/slider/slider-root.mjs.map +1 -1
  99. package/dist/slider/slider-thumb.mjs +1 -1
  100. package/dist/slider/slider-value.mjs +1 -1
  101. package/dist/switch/switch.mjs +2 -2
  102. package/dist/tabs/tabs-list.mjs +1 -1
  103. package/dist/tabs/tabs-panel.mjs +1 -1
  104. package/dist/tabs/tabs-root.mjs +2 -2
  105. package/dist/tabs/tabs-tab.mjs +1 -1
  106. package/dist/toast/toast-action.d.mts +4 -3
  107. package/dist/toast/toast-action.d.mts.map +1 -1
  108. package/dist/toast/toast-action.mjs +8 -6
  109. package/dist/toast/toast-action.mjs.map +1 -1
  110. package/dist/toast/toast-root.mjs +1 -1
  111. package/dist/toast/toast-viewport.mjs +3 -3
  112. package/dist/toggle/toggle.d.mts +4 -1
  113. package/dist/toggle/toggle.d.mts.map +1 -1
  114. package/dist/toggle/toggle.mjs +16 -10
  115. package/dist/toggle/toggle.mjs.map +1 -1
  116. package/dist/toggle-group/toggle-group-item.d.mts +6 -2
  117. package/dist/toggle-group/toggle-group-item.d.mts.map +1 -1
  118. package/dist/toggle-group/toggle-group-item.mjs +10 -5
  119. package/dist/toggle-group/toggle-group-item.mjs.map +1 -1
  120. package/dist/toggle-group/toggle-group-root.mjs +3 -3
  121. package/dist/toolbar/index.d.mts +4 -5
  122. package/dist/toolbar/index.d.mts.map +1 -1
  123. package/dist/toolbar/index.mjs +3 -4
  124. package/dist/toolbar/index.mjs.map +1 -1
  125. package/dist/toolbar/toolbar-root.mjs +1 -1
  126. package/dist/toolbar/toolbar-separator.mjs +1 -1
  127. package/package.json +2 -1
  128. package/dist/toolbar/toolbar-button.d.mts +0 -42
  129. package/dist/toolbar/toolbar-button.d.mts.map +0 -1
  130. package/dist/toolbar/toolbar-button.mjs +0 -50
  131. package/dist/toolbar/toolbar-button.mjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
3
2
  import { dataAttr } from "../internal/data-attr.mjs";
4
- import { rendersButton } from "../internal/render-element.mjs";
3
+ import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
4
+ import { isHostButton, rendersButton } from "../internal/render-element.mjs";
5
5
  import { useRender } from "../internal/use-render.mjs";
6
6
  import { useToggleGroupContext } from "./toggle-group-context.mjs";
7
7
  import { useCallback } from "react";
@@ -12,7 +12,7 @@ import { useCallback } from "react";
12
12
  * by the roving engine (the group's, or the enclosing Toolbar's).
13
13
  *
14
14
  * Owned keys (conventions 1.2): `type` (on a `<button>` only), `aria-pressed`, `disabled`,
15
- * `data-pressed`, `data-pending`, `data-disabled`, `data-orientation`, `onClick`, and
15
+ * `aria-disabled` (link or component `render`), `data-pressed`, `data-pending`, `data-disabled`, `data-orientation`, `onClick`, and
16
16
  * `focusgroupstart` while the Root renders `focusgroup`.
17
17
  */
18
18
  function ToggleGroupItem({ value, disabled: disabledProp = false, transition, className, style, children, render, ...rest }) {
@@ -22,6 +22,7 @@ function ToggleGroupItem({ value, disabled: disabledProp = false, transition, cl
22
22
  const disabled = ctx.disabled || disabledProp;
23
23
  const { register } = ctx;
24
24
  const registerRef = useCallback((el) => register(el, value), [register, value]);
25
+ const focusable = !isHostButton(render);
25
26
  const state = {
26
27
  pressed,
27
28
  pending,
@@ -40,7 +41,8 @@ function ToggleGroupItem({ value, disabled: disabledProp = false, transition, cl
40
41
  type: "button"
41
42
  } : rest,
42
43
  libraryProps: {
43
- disabled,
44
+ disabled: focusable ? void 0 : disabled,
45
+ ...focusable && { "aria-disabled": disabled ? true : void 0 },
44
46
  "aria-pressed": pressed,
45
47
  "data-pressed": dataAttr(pressed),
46
48
  "data-pending": dataAttr(pending),
@@ -48,7 +50,10 @@ function ToggleGroupItem({ value, disabled: disabledProp = false, transition, cl
48
50
  "data-orientation": ctx.orientation,
49
51
  ...ctx.focusgroupStartValue !== null && { focusgroupstart: ctx.focusgroupStartValue === value ? "" : void 0 },
50
52
  onClick: (event) => {
51
- if (disabled) return;
53
+ if (disabled) {
54
+ event.preventDefault();
55
+ return;
56
+ }
52
57
  ctx.toggle(value, event.nativeEvent);
53
58
  }
54
59
  },
@@ -1 +1 @@
1
- {"version":3,"file":"toggle-group-item.mjs","names":[],"sources":["../../src/toggle-group/toggle-group-item.tsx"],"sourcesContent":["\"use client\";\nimport { useCallback } from \"react\";\nimport type {\n ComponentPropsWithRef,\n CSSProperties,\n MouseEvent,\n ReactNode,\n ViewTransitionClass,\n} from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { useTransitionBoundary } from \"../internal/transition-boundary.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { rendersButton, useRender } from \"../internal/use-render.js\";\nimport { useToggleGroupContext } from \"./toggle-group-context.js\";\nimport type { ToggleGroupOrientation } from \"./toggle-group-context.js\";\n\nexport interface ToggleGroupItemState {\n /** Optimistic pressed state. */\n readonly pressed: boolean;\n /** The group's action is in flight and this Item's optimistic state differs from its committed one. */\n readonly pending: boolean;\n /** Own `disabled` or the Root's. */\n readonly disabled: boolean;\n readonly orientation: ToggleGroupOrientation;\n}\n\nexport interface ToggleGroupItemProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n \"onClick\" | \"type\" | \"value\" | \"tabIndex\" | \"aria-pressed\" | \"className\" | \"style\" | \"children\"\n> {\n /** The value this Item presses. Unique within the group. */\n value: string;\n /** Renders a native disabled button; never dispatches; skipped by arrow keys. */\n disabled?: boolean;\n /**\n * Forwarded as `default` to the Item's `<ViewTransition>`. As on Toggle: animates the commit\n * that ends the group's action (and rollbacks), not the optimistic flip, which is a CSS\n * `transition` on `[data-pressed]`. Static; any value makes a mount inside a transition start a\n * document view transition (issue #35).\n */\n transition?: ViewTransitionClass;\n className?: StateValue<string | undefined, ToggleGroupItemState>;\n style?: StateValue<CSSProperties | undefined, ToggleGroupItemState>;\n /** Rendered from optimistic state; must not suspend. */\n children?: StateValue<ReactNode, ToggleGroupItemState>;\n /** Must be, or render, a `<button>` (a toggle is a button). */\n render?: RenderProp<ComponentPropsWithRef<\"button\">, ToggleGroupItemState>;\n}\n\n/**\n * One toggle of a ToggleGroup: the `Toggle` element (`<button type=\"button\" aria-pressed>`) whose\n * pressed state is the Root's (design/components/toggle-group.md 16.3). Its `tabindex` is written\n * by the roving engine (the group's, or the enclosing Toolbar's).\n *\n * Owned keys (conventions 1.2): `type` (on a `<button>` only), `aria-pressed`, `disabled`,\n * `data-pressed`, `data-pending`, `data-disabled`, `data-orientation`, `onClick`, and\n * `focusgroupstart` while the Root renders `focusgroup`.\n */\nexport function ToggleGroupItem({\n value,\n disabled: disabledProp = false,\n transition,\n className,\n style,\n children,\n render,\n ...rest\n}: ToggleGroupItemProps) {\n const ctx = useToggleGroupContext(\"ToggleGroup.Item\");\n const pressed = ctx.optimistic.has(value);\n const pending = ctx.pending && pressed !== ctx.committed.has(value);\n const disabled = ctx.disabled || disabledProp;\n const { register } = ctx;\n const registerRef = useCallback((el: HTMLElement) => register(el, value), [register, value]);\n\n const state: ToggleGroupItemState = {\n pressed,\n pending,\n disabled,\n orientation: ctx.orientation,\n };\n\n const element = useRender<ComponentPropsWithRef<\"button\">, ToggleGroupItemState>({\n defaultElement: \"button\",\n render,\n state,\n className,\n style,\n children,\n // Pass-through layer, as Toggle: a `render` element's own `type` wins.\n props: rendersButton(render) ? { ...rest, type: \"button\" } : rest,\n libraryProps: {\n disabled,\n \"aria-pressed\": pressed,\n \"data-pressed\": dataAttr(pressed),\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(disabled),\n \"data-orientation\": ctx.orientation,\n ...(ctx.focusgroupStartValue !== null && {\n focusgroupstart: ctx.focusgroupStartValue === value ? \"\" : undefined,\n }),\n onClick: (event: MouseEvent<HTMLButtonElement>) => {\n // Native buttons do not fire `click` when disabled; the guard covers `render` elements.\n if (disabled) return;\n ctx.toggle(value, event.nativeEvent);\n },\n },\n ref: registerRef,\n });\n\n return useTransitionBoundary(\"ToggleGroup.Item\", transition, element);\n}\n\nToggleGroupItem.displayName = \"ToggleGroupItem\";\n"],"mappings":";;;;;;;;;;;;;;;;;AA0DA,SAAgB,gBAAgB,EAC9B,OACA,UAAU,eAAe,OACzB,YACA,WACA,OACA,UACA,QACA,GAAG,QACoB;CACvB,MAAM,MAAM,sBAAsB,kBAAkB;CACpD,MAAM,UAAU,IAAI,WAAW,IAAI,KAAK;CACxC,MAAM,UAAU,IAAI,WAAW,YAAY,IAAI,UAAU,IAAI,KAAK;CAClE,MAAM,WAAW,IAAI,YAAY;CACjC,MAAM,EAAE,aAAa;CACrB,MAAM,cAAc,aAAa,OAAoB,SAAS,IAAI,KAAK,GAAG,CAAC,UAAU,KAAK,CAAC;CAE3F,MAAM,QAA8B;EAClC;EACA;EACA;EACA,aAAa,IAAI;CACnB;CAEA,MAAM,UAAU,UAAiE;EAC/E,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EAEA,OAAO,cAAc,MAAM,IAAI;GAAE,GAAG;GAAM,MAAM;EAAS,IAAI;EAC7D,cAAc;GACZ;GACA,gBAAgB;GAChB,gBAAgB,SAAS,OAAO;GAChC,gBAAgB,SAAS,OAAO;GAChC,iBAAiB,SAAS,QAAQ;GAClC,oBAAoB,IAAI;GACxB,GAAI,IAAI,yBAAyB,QAAQ,EACvC,iBAAiB,IAAI,yBAAyB,QAAQ,KAAK,KAAA,EAC7D;GACA,UAAU,UAAyC;IAEjD,IAAI,UAAU;IACd,IAAI,OAAO,OAAO,MAAM,WAAW;GACrC;EACF;EACA,KAAK;CACP,CAAC;CAED,OAAO,sBAAsB,oBAAoB,YAAY,OAAO;AACtE;AAEA,gBAAgB,cAAc"}
1
+ {"version":3,"file":"toggle-group-item.mjs","names":[],"sources":["../../src/toggle-group/toggle-group-item.tsx"],"sourcesContent":["\"use client\";\nimport { useCallback } from \"react\";\nimport type {\n ComponentPropsWithRef,\n CSSProperties,\n MouseEvent,\n ReactNode,\n ViewTransitionClass,\n} from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { useTransitionBoundary } from \"../internal/transition-boundary.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { isHostButton, rendersButton, useRender } from \"../internal/use-render.js\";\nimport { useToggleGroupContext } from \"./toggle-group-context.js\";\nimport type { ToggleGroupOrientation } from \"./toggle-group-context.js\";\n\nexport interface ToggleGroupItemState {\n /** Optimistic pressed state. */\n readonly pressed: boolean;\n /** The group's action is in flight and this Item's optimistic state differs from its committed one. */\n readonly pending: boolean;\n /** Own `disabled` or the Root's. */\n readonly disabled: boolean;\n readonly orientation: ToggleGroupOrientation;\n}\n\nexport interface ToggleGroupItemProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n \"onClick\" | \"type\" | \"value\" | \"tabIndex\" | \"aria-pressed\" | \"className\" | \"style\" | \"children\"\n> {\n /** The value this Item presses. Unique within the group. */\n value: string;\n /**\n * Never dispatches. Native `disabled` on a `<button>` (skipped by the arrow keys); with a link\n * or component `render`, `aria-disabled=\"true\"` instead: the element stays focusable and the\n * arrow keys reach it (the APG Toolbar behaviour).\n */\n disabled?: boolean;\n /**\n * Forwarded as `default` to the Item's `<ViewTransition>`. As on Toggle: animates the commit\n * that ends the group's action (and rollbacks), not the optimistic flip, which is a CSS\n * `transition` on `[data-pressed]`. Static; any value makes a mount inside a transition start a\n * document view transition (issue #35).\n */\n transition?: ViewTransitionClass;\n className?: StateValue<string | undefined, ToggleGroupItemState>;\n style?: StateValue<CSSProperties | undefined, ToggleGroupItemState>;\n /** Rendered from optimistic state; must not suspend. */\n children?: StateValue<ReactNode, ToggleGroupItemState>;\n /** Must be, or render, a `<button>` (a toggle is a button). */\n render?: RenderProp<ComponentPropsWithRef<\"button\">, ToggleGroupItemState>;\n}\n\n/**\n * One toggle of a ToggleGroup: the `Toggle` element (`<button type=\"button\" aria-pressed>`) whose\n * pressed state is the Root's (design/components/toggle-group.md 16.3). Its `tabindex` is written\n * by the roving engine (the group's, or the enclosing Toolbar's).\n *\n * Owned keys (conventions 1.2): `type` (on a `<button>` only), `aria-pressed`, `disabled`,\n * `aria-disabled` (link or component `render`), `data-pressed`, `data-pending`, `data-disabled`, `data-orientation`, `onClick`, and\n * `focusgroupstart` while the Root renders `focusgroup`.\n */\nexport function ToggleGroupItem({\n value,\n disabled: disabledProp = false,\n transition,\n className,\n style,\n children,\n render,\n ...rest\n}: ToggleGroupItemProps) {\n const ctx = useToggleGroupContext(\"ToggleGroup.Item\");\n const pressed = ctx.optimistic.has(value);\n const pending = ctx.pending && pressed !== ctx.committed.has(value);\n const disabled = ctx.disabled || disabledProp;\n const { register } = ctx;\n const registerRef = useCallback((el: HTMLElement) => register(el, value), [register, value]);\n\n // Not a host <button> (a link, a component): `aria-disabled`, enforced by the click handler\n // (#83). The roving engine skips `:disabled` only, so such an Item is reached by the arrows.\n const focusable = !isHostButton(render);\n\n const state: ToggleGroupItemState = {\n pressed,\n pending,\n disabled,\n orientation: ctx.orientation,\n };\n\n const element = useRender<ComponentPropsWithRef<\"button\">, ToggleGroupItemState>({\n defaultElement: \"button\",\n render,\n state,\n className,\n style,\n children,\n // Pass-through layer, as Toggle: a `render` element's own `type` wins.\n props: rendersButton(render) ? { ...rest, type: \"button\" } : rest,\n libraryProps: {\n disabled: focusable ? undefined : disabled,\n // Owned only in the focusable branch: a host button keeps a consumer's own.\n ...(focusable && { \"aria-disabled\": disabled ? true : undefined }),\n \"aria-pressed\": pressed,\n \"data-pressed\": dataAttr(pressed),\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(disabled),\n \"data-orientation\": ctx.orientation,\n ...(ctx.focusgroupStartValue !== null && {\n focusgroupstart: ctx.focusgroupStartValue === value ? \"\" : undefined,\n }),\n onClick: (event: MouseEvent<HTMLButtonElement>) => {\n // Native buttons do not fire `click` when disabled; the guard covers `render` elements\n // (a link must not navigate either).\n if (disabled) {\n event.preventDefault();\n return;\n }\n ctx.toggle(value, event.nativeEvent);\n },\n },\n ref: registerRef,\n });\n\n return useTransitionBoundary(\"ToggleGroup.Item\", transition, element);\n}\n\nToggleGroupItem.displayName = \"ToggleGroupItem\";\n"],"mappings":";;;;;;;;;;;;;;;;;AA8DA,SAAgB,gBAAgB,EAC9B,OACA,UAAU,eAAe,OACzB,YACA,WACA,OACA,UACA,QACA,GAAG,QACoB;CACvB,MAAM,MAAM,sBAAsB,kBAAkB;CACpD,MAAM,UAAU,IAAI,WAAW,IAAI,KAAK;CACxC,MAAM,UAAU,IAAI,WAAW,YAAY,IAAI,UAAU,IAAI,KAAK;CAClE,MAAM,WAAW,IAAI,YAAY;CACjC,MAAM,EAAE,aAAa;CACrB,MAAM,cAAc,aAAa,OAAoB,SAAS,IAAI,KAAK,GAAG,CAAC,UAAU,KAAK,CAAC;CAI3F,MAAM,YAAY,CAAC,aAAa,MAAM;CAEtC,MAAM,QAA8B;EAClC;EACA;EACA;EACA,aAAa,IAAI;CACnB;CAEA,MAAM,UAAU,UAAiE;EAC/E,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EAEA,OAAO,cAAc,MAAM,IAAI;GAAE,GAAG;GAAM,MAAM;EAAS,IAAI;EAC7D,cAAc;GACZ,UAAU,YAAY,KAAA,IAAY;GAElC,GAAI,aAAa,EAAE,iBAAiB,WAAW,OAAO,KAAA,EAAU;GAChE,gBAAgB;GAChB,gBAAgB,SAAS,OAAO;GAChC,gBAAgB,SAAS,OAAO;GAChC,iBAAiB,SAAS,QAAQ;GAClC,oBAAoB,IAAI;GACxB,GAAI,IAAI,yBAAyB,QAAQ,EACvC,iBAAiB,IAAI,yBAAyB,QAAQ,KAAK,KAAA,EAC7D;GACA,UAAU,UAAyC;IAGjD,IAAI,UAAU;KACZ,MAAM,eAAe;KACrB;IACF;IACA,IAAI,OAAO,OAAO,MAAM,WAAW;GACrC;EACF;EACA,KAAK;CACP,CAAC;CAED,OAAO,sBAAsB,oBAAoB,YAAY,OAAO;AACtE;AAEA,gBAAgB,cAAc"}
@@ -1,13 +1,13 @@
1
1
  "use client";
2
2
  import { createActionDetails } from "../internal/action-details.mjs";
3
3
  import { dataAttr } from "../internal/data-attr.mjs";
4
+ import { useToolbarContext } from "../internal/toolbar-context.mjs";
5
+ import { useDevWarning } from "../internal/use-dev-warning.mjs";
6
+ import { useRender } from "../internal/use-render.mjs";
4
7
  import { transitionTypes } from "../internal/transition-types.mjs";
5
8
  import { useLatest } from "../internal/use-latest.mjs";
6
9
  import { useControllableAction } from "../internal/use-controllable-action.mjs";
7
- import { useRender } from "../internal/use-render.mjs";
8
10
  import { ToggleGroupContext } from "./toggle-group-context.mjs";
9
- import { useToolbarContext } from "../internal/toolbar-context.mjs";
10
- import { useDevWarning } from "../internal/use-dev-warning.mjs";
11
11
  import { useRovingFocus } from "../internal/use-roving-focus.mjs";
12
12
  import { useCallback, useEffectEvent, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
13
13
  import { jsx } from "react/jsx-runtime";
@@ -1,18 +1,17 @@
1
1
  import "../internal/platform-attributes.mjs";
2
- import { ToolbarButton, ToolbarButtonActionDetails, ToolbarButtonProps, ToolbarButtonState } from "./toolbar-button.mjs";
3
2
  import { ToolbarOrientation, ToolbarRoot, ToolbarRootProps, ToolbarRootState } from "./toolbar-root.mjs";
4
3
  import { ToolbarSeparator, ToolbarSeparatorProps, ToolbarSeparatorState } from "./toolbar-separator.mjs";
5
4
  //#region src/toolbar/index.d.ts
6
5
  /**
7
6
  * Toolbar (WAI-ARIA APG Toolbar pattern): `Root` (div role="toolbar") with one Tab stop and
8
- * arrow keys over its focusable descendants, `Button` (an action button, focusable when
9
- * disabled) and `Separator` (hr). Any focusable element is an item: no wrapper parts.
7
+ * arrow keys over its focusable descendants, and `Separator` (hr). Any focusable element is an
8
+ * item: no wrapper parts. A command button is `Button` from `@funstack/ui/button`, which stays
9
+ * focusable when disabled inside a Toolbar (design/components/button.md 7.3).
10
10
  */
11
11
  export declare const Toolbar: {
12
12
  readonly Root: typeof ToolbarRoot;
13
- readonly Button: typeof ToolbarButton;
14
13
  readonly Separator: typeof ToolbarSeparator;
15
14
  };
16
15
  //#endregion
17
- export type { ToolbarButtonActionDetails, ToolbarButtonProps, ToolbarButtonState, ToolbarOrientation, ToolbarRootProps, ToolbarRootState, ToolbarSeparatorProps, ToolbarSeparatorState };
16
+ export type { ToolbarOrientation, ToolbarRootProps, ToolbarRootState, ToolbarSeparatorProps, ToolbarSeparatorState };
18
17
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/toolbar/index.ts"],"mappings":";;;;;;;;;;qBAWa;WACX,aAAI;WACJ,eAAM;WACN,kBAAS"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/toolbar/index.ts"],"mappings":";;;;;;;;;;qBAWa;WACX,aAAI;WACJ,kBAAS"}
@@ -1,15 +1,14 @@
1
- import { ToolbarButton } from "./toolbar-button.mjs";
2
1
  import { ToolbarRoot } from "./toolbar-root.mjs";
3
2
  import { ToolbarSeparator } from "./toolbar-separator.mjs";
4
3
  //#region src/toolbar/index.ts
5
4
  /**
6
5
  * Toolbar (WAI-ARIA APG Toolbar pattern): `Root` (div role="toolbar") with one Tab stop and
7
- * arrow keys over its focusable descendants, `Button` (an action button, focusable when
8
- * disabled) and `Separator` (hr). Any focusable element is an item: no wrapper parts.
6
+ * arrow keys over its focusable descendants, and `Separator` (hr). Any focusable element is an
7
+ * item: no wrapper parts. A command button is `Button` from `@funstack/ui/button`, which stays
8
+ * focusable when disabled inside a Toolbar (design/components/button.md 7.3).
9
9
  */
10
10
  const Toolbar = {
11
11
  Root: ToolbarRoot,
12
- Button: ToolbarButton,
13
12
  Separator: ToolbarSeparator
14
13
  };
15
14
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/toolbar/index.ts"],"sourcesContent":["// Ships the platform attribute typings with this subpath (conventions 7.4). Type-only.\nimport \"../internal/platform-attributes.js\";\nimport { ToolbarButton } from \"./toolbar-button.js\";\nimport { ToolbarRoot } from \"./toolbar-root.js\";\nimport { ToolbarSeparator } from \"./toolbar-separator.js\";\n\n/**\n * Toolbar (WAI-ARIA APG Toolbar pattern): `Root` (div role=\"toolbar\") with one Tab stop and\n * arrow keys over its focusable descendants, `Button` (an action button, focusable when\n * disabled) and `Separator` (hr). Any focusable element is an item: no wrapper parts.\n */\nexport const Toolbar = {\n Root: ToolbarRoot,\n Button: ToolbarButton,\n Separator: ToolbarSeparator,\n} as const;\n\nexport type { ToolbarRootProps, ToolbarRootState, ToolbarOrientation } from \"./toolbar-root.js\";\nexport type {\n ToolbarButtonProps,\n ToolbarButtonState,\n ToolbarButtonActionDetails,\n} from \"./toolbar-button.js\";\nexport type { ToolbarSeparatorProps, ToolbarSeparatorState } from \"./toolbar-separator.js\";\n"],"mappings":";;;;;;;;;AAWA,MAAa,UAAU;CACrB,MAAM;CACN,QAAQ;CACR,WAAW;AACb"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/toolbar/index.ts"],"sourcesContent":["// Ships the platform attribute typings with this subpath (conventions 7.4). Type-only.\nimport \"../internal/platform-attributes.js\";\nimport { ToolbarRoot } from \"./toolbar-root.js\";\nimport { ToolbarSeparator } from \"./toolbar-separator.js\";\n\n/**\n * Toolbar (WAI-ARIA APG Toolbar pattern): `Root` (div role=\"toolbar\") with one Tab stop and\n * arrow keys over its focusable descendants, and `Separator` (hr). Any focusable element is an\n * item: no wrapper parts. A command button is `Button` from `@funstack/ui/button`, which stays\n * focusable when disabled inside a Toolbar (design/components/button.md 7.3).\n */\nexport const Toolbar = {\n Root: ToolbarRoot,\n Separator: ToolbarSeparator,\n} as const;\n\nexport type { ToolbarRootProps, ToolbarRootState, ToolbarOrientation } from \"./toolbar-root.js\";\nexport type { ToolbarSeparatorProps, ToolbarSeparatorState } from \"./toolbar-separator.js\";\n"],"mappings":";;;;;;;;;AAWA,MAAa,UAAU;CACrB,MAAM;CACN,WAAW;AACb"}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import { useRender } from "../internal/use-render.mjs";
3
2
  import { ToolbarContext } from "../internal/toolbar-context.mjs";
3
+ import { useRender } from "../internal/use-render.mjs";
4
4
  import { useRovingFocus } from "../internal/use-roving-focus.mjs";
5
5
  import { useMemo, useRef, useSyncExternalStore } from "react";
6
6
  import { jsx } from "react/jsx-runtime";
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import { useRender } from "../internal/use-render.mjs";
3
2
  import { useToolbarContext } from "../internal/toolbar-context.mjs";
3
+ import { useRender } from "../internal/use-render.mjs";
4
4
  //#region src/toolbar/toolbar-separator.tsx
5
5
  /**
6
6
  * `<hr aria-orientation>` between toolbar items: vertical in a horizontal Toolbar, horizontal in
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funstack/ui",
3
- "version": "0.1.0-alpha.5",
3
+ "version": "0.1.0-alpha.7",
4
4
  "description": "Headless UI library for React — the first Async React-native UI library",
5
5
  "keywords": [
6
6
  "components",
@@ -30,6 +30,7 @@
30
30
  "exports": {
31
31
  ".": "./dist/index.mjs",
32
32
  "./accordion": "./dist/accordion/index.mjs",
33
+ "./button": "./dist/button/index.mjs",
33
34
  "./checkbox": "./dist/checkbox/index.mjs",
34
35
  "./checkbox-group": "./dist/checkbox-group/index.mjs",
35
36
  "./combobox": "./dist/combobox/index.mjs",
@@ -1,42 +0,0 @@
1
- import { Action, ActionDetails, RenderProp, StateValue } from "../internal/types.mjs";
2
- import { CSSProperties, ComponentPropsWithRef, ReactNode, ViewTransitionClass } from "react";
3
- //#region src/toolbar/toolbar-button.d.ts
4
- /** Details passed to `Toolbar.Button`'s `action`. */
5
- export interface ToolbarButtonActionDetails extends ActionDetails {}
6
- export interface ToolbarButtonState {
7
- /** This button's action is in flight. */
8
- readonly pending: boolean;
9
- readonly disabled: boolean;
10
- }
11
- export interface ToolbarButtonProps extends Omit<ComponentPropsWithRef<"button">, "onClick" | "type" | "tabIndex" | "aria-disabled" | "className" | "style" | "children"> {
12
- /** Runs inside this button's own transition on click, Enter or Space. Sync or async; rejections reach the nearest Error Boundary. */
13
- action?: Action<[details: ToolbarButtonActionDetails]>;
14
- /**
15
- * `aria-disabled="true"`: the button stays focusable and in the arrow-key sequence so
16
- * assistive technology still finds it (APG Toolbar example), and never dispatches.
17
- */
18
- disabled?: boolean;
19
- /**
20
- * Forwarded as `default` to the button's `<ViewTransition>`: animates the commit that ends the
21
- * action (content keyed on `pending`), not a click. Static; any value makes a mount inside a
22
- * transition start a document view transition (issue #35).
23
- */
24
- transition?: ViewTransitionClass;
25
- className?: StateValue<string | undefined, ToolbarButtonState>;
26
- style?: StateValue<CSSProperties | undefined, ToolbarButtonState>;
27
- children?: StateValue<ReactNode, ToolbarButtonState>;
28
- render?: RenderProp<ComponentPropsWithRef<"button">, ToolbarButtonState>;
29
- }
30
- /**
31
- * A toolbar command: `<button type="button">` that runs `action` in its own transition
32
- * (`data-pending` while it runs). Disabled is `aria-disabled`, so it stays focusable.
33
- *
34
- * Owned keys (conventions 1.2): `type` (on a `<button>` only), `aria-disabled`, `data-pending`,
35
- * `data-disabled`, `onClick`.
36
- */
37
- export declare function ToolbarButton({ action, disabled, transition, className, style, children, render, ...rest }: ToolbarButtonProps): ReactNode;
38
- export declare namespace ToolbarButton {
39
- var displayName: string;
40
- }
41
- //#endregion
42
- //# sourceMappingURL=toolbar-button.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"toolbar-button.d.mts","names":[],"sources":["../../src/toolbar/toolbar-button.tsx"],"mappings":";;;;iBAgBiB,mCAAmC;iBAEnC;;WAEN;WACA;;iBAGM,2BAA2B,KAC1C;;EAIA,SAAS,QAAQ,SAAS;;;;;EAK1B;;;;;;EAMA,aAAa;EACb,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;EACjC,SAAS,WAAW,iCAAiC;;;;;;;;;wBAUvC,gBACd,QACA,UACA,YACA,WACA,OACA,UACA,WACG,QACF,qBAAkB;yBATL"}
@@ -1,50 +0,0 @@
1
- "use client";
2
- import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
3
- import { createActionDetails } from "../internal/action-details.mjs";
4
- import { dataAttr } from "../internal/data-attr.mjs";
5
- import { rendersButton } from "../internal/render-element.mjs";
6
- import { useRender } from "../internal/use-render.mjs";
7
- import { useActionTrigger } from "../internal/use-action-trigger.mjs";
8
- //#region src/toolbar/toolbar-button.tsx
9
- /**
10
- * A toolbar command: `<button type="button">` that runs `action` in its own transition
11
- * (`data-pending` while it runs). Disabled is `aria-disabled`, so it stays focusable.
12
- *
13
- * Owned keys (conventions 1.2): `type` (on a `<button>` only), `aria-disabled`, `data-pending`,
14
- * `data-disabled`, `onClick`.
15
- */
16
- function ToolbarButton({ action, disabled = false, transition, className, style, children, render, ...rest }) {
17
- const { pending, run } = useActionTrigger();
18
- const element = useRender({
19
- defaultElement: "button",
20
- render,
21
- state: {
22
- pending,
23
- disabled
24
- },
25
- className,
26
- style,
27
- children,
28
- props: rest,
29
- libraryProps: {
30
- ...rendersButton(render) && { type: "button" },
31
- "aria-disabled": disabled ? true : void 0,
32
- "data-pending": dataAttr(pending),
33
- "data-disabled": dataAttr(disabled),
34
- onClick: (event) => {
35
- if (disabled) {
36
- event.preventDefault();
37
- return;
38
- }
39
- const details = createActionDetails(event.nativeEvent, {});
40
- run(() => action?.(details));
41
- }
42
- }
43
- });
44
- return useTransitionBoundary("Toolbar.Button", transition, element);
45
- }
46
- ToolbarButton.displayName = "ToolbarButton";
47
- //#endregion
48
- export { ToolbarButton };
49
-
50
- //# sourceMappingURL=toolbar-button.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"toolbar-button.mjs","names":[],"sources":["../../src/toolbar/toolbar-button.tsx"],"sourcesContent":["\"use client\";\nimport type {\n ComponentPropsWithRef,\n CSSProperties,\n MouseEvent,\n ReactNode,\n ViewTransitionClass,\n} from \"react\";\nimport { createActionDetails } from \"../internal/action-details.js\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { useTransitionBoundary } from \"../internal/transition-boundary.js\";\nimport type { Action, ActionDetails, RenderProp, StateValue } from \"../internal/types.js\";\nimport { useActionTrigger } from \"../internal/use-action-trigger.js\";\nimport { rendersButton, useRender } from \"../internal/use-render.js\";\n\n/** Details passed to `Toolbar.Button`'s `action`. */\nexport interface ToolbarButtonActionDetails extends ActionDetails {}\n\nexport interface ToolbarButtonState {\n /** This button's action is in flight. */\n readonly pending: boolean;\n readonly disabled: boolean;\n}\n\nexport interface ToolbarButtonProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n \"onClick\" | \"type\" | \"tabIndex\" | \"aria-disabled\" | \"className\" | \"style\" | \"children\"\n> {\n /** Runs inside this button's own transition on click, Enter or Space. Sync or async; rejections reach the nearest Error Boundary. */\n action?: Action<[details: ToolbarButtonActionDetails]>;\n /**\n * `aria-disabled=\"true\"`: the button stays focusable and in the arrow-key sequence so\n * assistive technology still finds it (APG Toolbar example), and never dispatches.\n */\n disabled?: boolean;\n /**\n * Forwarded as `default` to the button's `<ViewTransition>`: animates the commit that ends the\n * action (content keyed on `pending`), not a click. Static; any value makes a mount inside a\n * transition start a document view transition (issue #35).\n */\n transition?: ViewTransitionClass;\n className?: StateValue<string | undefined, ToolbarButtonState>;\n style?: StateValue<CSSProperties | undefined, ToolbarButtonState>;\n children?: StateValue<ReactNode, ToolbarButtonState>;\n render?: RenderProp<ComponentPropsWithRef<\"button\">, ToolbarButtonState>;\n}\n\n/**\n * A toolbar command: `<button type=\"button\">` that runs `action` in its own transition\n * (`data-pending` while it runs). Disabled is `aria-disabled`, so it stays focusable.\n *\n * Owned keys (conventions 1.2): `type` (on a `<button>` only), `aria-disabled`, `data-pending`,\n * `data-disabled`, `onClick`.\n */\nexport function ToolbarButton({\n action,\n disabled = false,\n transition,\n className,\n style,\n children,\n render,\n ...rest\n}: ToolbarButtonProps) {\n const { pending, run } = useActionTrigger();\n const state: ToolbarButtonState = { pending, disabled };\n\n const element = useRender<ComponentPropsWithRef<\"button\">, ToolbarButtonState>({\n defaultElement: \"button\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps: {\n ...(rendersButton(render) && { type: \"button\" as const }),\n \"aria-disabled\": disabled ? true : undefined,\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(disabled),\n onClick: (event: MouseEvent<HTMLButtonElement>) => {\n if (disabled) {\n // A disabled link must not navigate either.\n event.preventDefault();\n return;\n }\n const details: ToolbarButtonActionDetails = createActionDetails(event.nativeEvent, {});\n run(() => action?.(details));\n },\n },\n });\n\n return useTransitionBoundary(\"Toolbar.Button\", transition, element);\n}\n\nToolbarButton.displayName = \"ToolbarButton\";\n"],"mappings":";;;;;;;;;;;;;;;AAsDA,SAAgB,cAAc,EAC5B,QACA,WAAW,OACX,YACA,WACA,OACA,UACA,QACA,GAAG,QACkB;CACrB,MAAM,EAAE,SAAS,QAAQ,iBAAiB;CAG1C,MAAM,UAAU,UAA+D;EAC7E,gBAAgB;EAChB;EACA,OAAA;GALkC;GAAS;EAKvC;EACJ;EACA;EACA;EACA,OAAO;EACP,cAAc;GACZ,GAAI,cAAc,MAAM,KAAK,EAAE,MAAM,SAAkB;GACvD,iBAAiB,WAAW,OAAO,KAAA;GACnC,gBAAgB,SAAS,OAAO;GAChC,iBAAiB,SAAS,QAAQ;GAClC,UAAU,UAAyC;IACjD,IAAI,UAAU;KAEZ,MAAM,eAAe;KACrB;IACF;IACA,MAAM,UAAsC,oBAAoB,MAAM,aAAa,CAAC,CAAC;IACrF,UAAU,SAAS,OAAO,CAAC;GAC7B;EACF;CACF,CAAC;CAED,OAAO,sBAAsB,kBAAkB,YAAY,OAAO;AACpE;AAEA,cAAc,cAAc"}