ajo-ui 0.1.0

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 (103) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +126 -0
  3. package/dist/accordion.js +130 -0
  4. package/dist/avatar.js +54 -0
  5. package/dist/calendar.js +2 -0
  6. package/dist/carousel.js +239 -0
  7. package/dist/chart.js +790 -0
  8. package/dist/checkbox-group.js +70 -0
  9. package/dist/checkbox.js +77 -0
  10. package/dist/chunks/bar-CVafh6C1.js +99 -0
  11. package/dist/chunks/calendar-q8jZ8Cxr.js +1923 -0
  12. package/dist/chunks/collection-DtRB63U4.js +111 -0
  13. package/dist/chunks/data-table-DpkWv4y4.js +1039 -0
  14. package/dist/chunks/menu-B45IyHHC.js +704 -0
  15. package/dist/chunks/native-BJdhd9XJ.js +20 -0
  16. package/dist/chunks/popup-C8Bb3l_g.js +459 -0
  17. package/dist/chunks/popup-surface-BDCgtVU0.js +18 -0
  18. package/dist/chunks/position-D6_i_SRn.js +434 -0
  19. package/dist/chunks/virtual-list-B7hjGkjk.js +413 -0
  20. package/dist/collapsible.js +106 -0
  21. package/dist/command.js +263 -0
  22. package/dist/context-menu.js +112 -0
  23. package/dist/data-table.js +5 -0
  24. package/dist/dialog.js +207 -0
  25. package/dist/direction.js +22 -0
  26. package/dist/drawer.js +139 -0
  27. package/dist/field.js +26 -0
  28. package/dist/index.js +38 -0
  29. package/dist/input-date.js +994 -0
  30. package/dist/input-group.js +52 -0
  31. package/dist/input-otp.js +179 -0
  32. package/dist/menu.js +2 -0
  33. package/dist/menubar.js +236 -0
  34. package/dist/message-scroller.js +446 -0
  35. package/dist/navigation-menu.js +330 -0
  36. package/dist/popover.js +307 -0
  37. package/dist/progress.js +39 -0
  38. package/dist/radio-group.js +107 -0
  39. package/dist/resizable.js +172 -0
  40. package/dist/select.js +961 -0
  41. package/dist/sidebar.js +343 -0
  42. package/dist/slider.js +259 -0
  43. package/dist/switch.js +53 -0
  44. package/dist/tabs.js +182 -0
  45. package/dist/toast.js +492 -0
  46. package/dist/toggle-group.js +111 -0
  47. package/dist/toggle.js +52 -0
  48. package/dist/toolbar.js +127 -0
  49. package/dist/tooltip.js +196 -0
  50. package/dist/utils.js +104 -0
  51. package/dist/virtual-list.js +2 -0
  52. package/package.json +250 -0
  53. package/src/accordion.tsx +261 -0
  54. package/src/availability.ts +261 -0
  55. package/src/avatar.tsx +99 -0
  56. package/src/bar.ts +156 -0
  57. package/src/calendar.tsx +1441 -0
  58. package/src/carousel.tsx +424 -0
  59. package/src/chart.tsx +1194 -0
  60. package/src/checkbox-group.tsx +132 -0
  61. package/src/checkbox.tsx +130 -0
  62. package/src/collapsible.tsx +188 -0
  63. package/src/collection.ts +154 -0
  64. package/src/command.tsx +511 -0
  65. package/src/context-menu.tsx +233 -0
  66. package/src/data-table-contract.ts +143 -0
  67. package/src/data-table-model.ts +760 -0
  68. package/src/data-table.tsx +475 -0
  69. package/src/dialog.tsx +393 -0
  70. package/src/direction.tsx +45 -0
  71. package/src/drawer.tsx +251 -0
  72. package/src/field.tsx +61 -0
  73. package/src/index.ts +37 -0
  74. package/src/input-date.tsx +1539 -0
  75. package/src/input-group.tsx +142 -0
  76. package/src/input-otp.tsx +324 -0
  77. package/src/menu-cluster.ts +124 -0
  78. package/src/menu.tsx +1095 -0
  79. package/src/menubar.tsx +459 -0
  80. package/src/message-scroller.tsx +732 -0
  81. package/src/native.ts +26 -0
  82. package/src/navigation-menu.tsx +578 -0
  83. package/src/popover.tsx +519 -0
  84. package/src/popup-surface.tsx +31 -0
  85. package/src/popup.ts +569 -0
  86. package/src/position.ts +523 -0
  87. package/src/progress.tsx +70 -0
  88. package/src/radio-group.tsx +186 -0
  89. package/src/resizable.tsx +310 -0
  90. package/src/segments.ts +922 -0
  91. package/src/select.tsx +1501 -0
  92. package/src/sidebar.tsx +683 -0
  93. package/src/slider.tsx +424 -0
  94. package/src/switch.tsx +104 -0
  95. package/src/tabs.tsx +314 -0
  96. package/src/toast.tsx +923 -0
  97. package/src/toggle-group.tsx +249 -0
  98. package/src/toggle.tsx +91 -0
  99. package/src/toolbar.tsx +212 -0
  100. package/src/tooltip.tsx +359 -0
  101. package/src/utils.ts +204 -0
  102. package/src/virtual-list.tsx +205 -0
  103. package/src/virtual.ts +385 -0
@@ -0,0 +1,70 @@
1
+ import { flag, strings } from "./utils.js";
2
+ import { Checkbox } from "./checkbox.js";
3
+ import { selection, statefulRootAttrs } from "ajo-cloves";
4
+ import { context } from "ajo/context";
5
+ import { Fragment, jsx } from "ajo/jsx-runtime";
6
+ //#region packages/ajo-ui/src/checkbox-group.tsx
7
+ var CheckboxGroupContext = context(null);
8
+ var CheckboxGroupRoot = function* ({ defaultValue }) {
9
+ let disabled = false;
10
+ let name;
11
+ let onValueChange;
12
+ const sel = selection(this, {
13
+ multiple: () => true,
14
+ fallback: strings(defaultValue),
15
+ onChange: (next, event) => onValueChange?.(next, event)
16
+ });
17
+ const checked = (value) => sel.has(value);
18
+ const change = (value, _checked, event) => {
19
+ if (disabled) return;
20
+ sel.toggle(value, event);
21
+ };
22
+ for (const args of this) {
23
+ disabled = Boolean(args.disabled);
24
+ name = args.name;
25
+ onValueChange = args.onValueChange;
26
+ sel.sync(args.value != null ? strings(args.value) : void 0);
27
+ CheckboxGroupContext({
28
+ checked,
29
+ disabled,
30
+ name,
31
+ toggle: change
32
+ });
33
+ yield /* @__PURE__ */ jsx(Fragment, { children: args.children });
34
+ }
35
+ };
36
+ /** Unstyled checkbox group cascading checked values, name, and disabled state to its items. */
37
+ var CheckboxGroup = ({ children, defaultValue, disabled, name, onValueChange, role = "group", value, ...attrs }) => {
38
+ const disabledFlag = Boolean(disabled);
39
+ return /* @__PURE__ */ jsx(CheckboxGroupRoot, {
40
+ ...statefulRootAttrs(attrs),
41
+ defaultValue,
42
+ disabled: disabledFlag,
43
+ name,
44
+ onValueChange,
45
+ value,
46
+ "attr:aria-disabled": flag(disabledFlag),
47
+ "attr:data-disabled": flag(disabledFlag),
48
+ "attr:data-slot": "checkbox-group",
49
+ "attr:role": role,
50
+ children
51
+ });
52
+ };
53
+ /** Unstyled native checkbox item wired to the nearest group. */
54
+ var CheckboxGroupItem = ({ disabled, name, value, ...attrs }) => {
55
+ const group = CheckboxGroupContext();
56
+ const item = String(value);
57
+ const checked = group?.checked(item) ?? false;
58
+ return /* @__PURE__ */ jsx(Checkbox, {
59
+ ...attrs,
60
+ checked,
61
+ "data-slot": "checkbox-group-item",
62
+ disabled: disabled ?? group?.disabled,
63
+ name: name ?? group?.name,
64
+ "set:checked": checked,
65
+ value: item,
66
+ onCheckedChange: (next, event) => group?.toggle(item, next, event)
67
+ });
68
+ };
69
+ //#endregion
70
+ export { CheckboxGroup, CheckboxGroupItem };
@@ -0,0 +1,77 @@
1
+ import { ariaChecked, bool, flag, syncCheckedState } from "./utils.js";
2
+ import { callHandler, callRef, dom } from "ajo-cloves";
3
+ import { Fragment, jsx, jsxs } from "ajo/jsx-runtime";
4
+ //#region packages/ajo-ui/src/checkbox.tsx
5
+ var stateFromAttrs = (attrs) => {
6
+ if (bool(attrs["set:indeterminate"])) return "indeterminate";
7
+ return bool(attrs["set:checked"] ?? attrs.checked ?? attrs.defaultChecked) ? "checked" : "unchecked";
8
+ };
9
+ var CheckboxRoot = function* () {
10
+ let input = null;
11
+ const sync = () => {
12
+ if (input) syncCheckedState(input, dom(this) ? this : null);
13
+ };
14
+ for (const { checkedIndicatorClass, inputAttrs, inputClass, indeterminateIndicatorClass, onCheckedChange } of this) {
15
+ const { class: _class, ref, "set:onchange": onChange, "set:oninput": onInput, type: _type, ...attrs } = inputAttrs;
16
+ const state = stateFromAttrs(inputAttrs);
17
+ if (dom(this)) this.dataset.state = state;
18
+ yield /* @__PURE__ */ jsxs(Fragment, { children: [
19
+ /* @__PURE__ */ jsx("input", {
20
+ ...attrs,
21
+ "aria-checked": ariaChecked(state),
22
+ class: inputClass,
23
+ "data-slot": "checkbox-input",
24
+ "data-state": state,
25
+ ref: (element) => {
26
+ input = element;
27
+ callRef(ref, element);
28
+ if (element) queueMicrotask(sync);
29
+ },
30
+ "set:onchange": (event) => {
31
+ callHandler(onChange, event);
32
+ sync();
33
+ onCheckedChange?.(event.currentTarget.checked, event);
34
+ },
35
+ "set:oninput": (event) => {
36
+ callHandler(onInput, event);
37
+ sync();
38
+ },
39
+ type: "checkbox"
40
+ }),
41
+ /* @__PURE__ */ jsx("span", {
42
+ "aria-hidden": "true",
43
+ class: checkedIndicatorClass,
44
+ "data-slot": "checkbox-indicator",
45
+ "data-state": "checked"
46
+ }),
47
+ /* @__PURE__ */ jsx("span", {
48
+ "aria-hidden": "true",
49
+ class: indeterminateIndicatorClass,
50
+ "data-slot": "checkbox-indicator",
51
+ "data-state": "indeterminate"
52
+ })
53
+ ] });
54
+ }
55
+ };
56
+ CheckboxRoot.is = "span";
57
+ /** Unstyled native checkbox with state slots and form behavior. */
58
+ var Checkbox = ({ checkedIndicatorClass, class: classes, disabled, inputClass, indeterminateIndicatorClass, onCheckedChange, ...attrs }) => {
59
+ const inputAttrs = {
60
+ ...attrs,
61
+ disabled
62
+ };
63
+ const state = stateFromAttrs(inputAttrs);
64
+ return /* @__PURE__ */ jsx(CheckboxRoot, {
65
+ checkedIndicatorClass,
66
+ inputAttrs,
67
+ inputClass,
68
+ indeterminateIndicatorClass,
69
+ onCheckedChange,
70
+ "attr:class": classes,
71
+ "attr:data-disabled": flag(disabled),
72
+ "attr:data-slot": attrs["data-slot"] ?? "checkbox",
73
+ "attr:data-state": state
74
+ });
75
+ };
76
+ //#endregion
77
+ export { Checkbox };
@@ -0,0 +1,99 @@
1
+ import { controlled, dom, roving, typeahead } from "ajo-cloves";
2
+ //#region packages/ajo-ui/src/bar.ts
3
+ /**
4
+ * The shared root machine for horizontal trigger bars (menubar,
5
+ * navigation-menu): one controlled open value ('' = closed), roving over a
6
+ * live trigger row with typeahead, and the open-follows-focus/hover policy.
7
+ *
8
+ * Movement (arrows, typeahead) only focuses the target trigger; the follow
9
+ * policy runs exactly once through the trigger's own focus handler, so
10
+ * controlled consumers see a single onValueChange per move.
11
+ */
12
+ var bar = (host, opts) => {
13
+ const read = opts.value ?? ((trigger) => trigger.dataset.value ?? "");
14
+ const state = controlled(host, {
15
+ fallback: opts.initialValue ?? "",
16
+ onChange: opts.onValueChange
17
+ });
18
+ let focused = "";
19
+ const stop = () => {
20
+ if (!dom(host)) return "";
21
+ const row = opts.triggers();
22
+ if (!row.length) return "";
23
+ return focused && row.some((trigger) => read(trigger) === focused) ? focused : read(row[0]);
24
+ };
25
+ const setValue = (next, event) => {
26
+ if (next && opts.disabled?.()) return;
27
+ if (next === state.value) return;
28
+ if (next) focused = next;
29
+ state.set(next, event);
30
+ };
31
+ let following = false;
32
+ const follow = (next, event) => {
33
+ if (following) return;
34
+ if (!state.value || !next || next === state.value) return;
35
+ following = true;
36
+ try {
37
+ if (dom(host)) {
38
+ const row = opts.triggers();
39
+ const target = row.find((trigger) => read(trigger) === next);
40
+ const active = document.activeElement;
41
+ if (target && active && active !== target && host.contains(active) && !row.includes(active)) target.focus();
42
+ }
43
+ setValue(next, event);
44
+ } finally {
45
+ following = false;
46
+ }
47
+ };
48
+ const nav = roving(host, {
49
+ items: opts.triggers,
50
+ orientation: () => "horizontal",
51
+ loop: () => opts.loop?.() ?? true,
52
+ onMove: (target) => target.focus()
53
+ });
54
+ const ta = typeahead(host, {
55
+ items: opts.triggers,
56
+ onMatch: (target, event) => {
57
+ event.preventDefault();
58
+ target.focus();
59
+ }
60
+ });
61
+ return {
62
+ get value() {
63
+ return state.value;
64
+ },
65
+ get focused() {
66
+ return focused;
67
+ },
68
+ sync: (value) => state.sync(value),
69
+ setValue,
70
+ close: (event) => setValue("", event),
71
+ follow,
72
+ focus(next, event) {
73
+ if (state.value && next && next !== state.value) follow(next, event);
74
+ else if (focused !== next) {
75
+ focused = next;
76
+ host.next();
77
+ }
78
+ },
79
+ adopt(next) {
80
+ focused = next;
81
+ },
82
+ isTabbable(value) {
83
+ const current = stop();
84
+ return !current || current === value;
85
+ },
86
+ handle(event) {
87
+ if (nav.handle(event)) return true;
88
+ if (event.key === "Escape") {
89
+ if (!state.value) return false;
90
+ event.preventDefault();
91
+ setValue("", event);
92
+ return true;
93
+ }
94
+ return ta.handle(event);
95
+ }
96
+ };
97
+ };
98
+ //#endregion
99
+ export { bar as t };