@hjmds/react 0.8.2

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 (135) hide show
  1. package/README.md +146 -0
  2. package/dist/actions.d.ts +61 -0
  3. package/dist/actions.d.ts.map +1 -0
  4. package/dist/actions.js +54 -0
  5. package/dist/actions.js.map +1 -0
  6. package/dist/advanced-display.d.ts +133 -0
  7. package/dist/advanced-display.d.ts.map +1 -0
  8. package/dist/advanced-display.js +201 -0
  9. package/dist/advanced-display.js.map +1 -0
  10. package/dist/advanced-forms.d.ts +116 -0
  11. package/dist/advanced-forms.d.ts.map +1 -0
  12. package/dist/advanced-forms.js +234 -0
  13. package/dist/advanced-forms.js.map +1 -0
  14. package/dist/advanced-navigation.d.ts +24 -0
  15. package/dist/advanced-navigation.d.ts.map +1 -0
  16. package/dist/advanced-navigation.js +25 -0
  17. package/dist/advanced-navigation.js.map +1 -0
  18. package/dist/bottom-navigation.d.ts +37 -0
  19. package/dist/bottom-navigation.d.ts.map +1 -0
  20. package/dist/bottom-navigation.js +132 -0
  21. package/dist/bottom-navigation.js.map +1 -0
  22. package/dist/date-picker.d.ts +24 -0
  23. package/dist/date-picker.d.ts.map +1 -0
  24. package/dist/date-picker.js +81 -0
  25. package/dist/date-picker.js.map +1 -0
  26. package/dist/display-public.d.ts +5 -0
  27. package/dist/display-public.d.ts.map +1 -0
  28. package/dist/display-public.js +5 -0
  29. package/dist/display-public.js.map +1 -0
  30. package/dist/display.d.ts +77 -0
  31. package/dist/display.d.ts.map +1 -0
  32. package/dist/display.js +51 -0
  33. package/dist/display.js.map +1 -0
  34. package/dist/evidence.d.ts +940 -0
  35. package/dist/evidence.d.ts.map +1 -0
  36. package/dist/evidence.js +98 -0
  37. package/dist/evidence.js.map +1 -0
  38. package/dist/feedback.d.ts +89 -0
  39. package/dist/feedback.d.ts.map +1 -0
  40. package/dist/feedback.js +41 -0
  41. package/dist/feedback.js.map +1 -0
  42. package/dist/file-picker.d.ts +30 -0
  43. package/dist/file-picker.d.ts.map +1 -0
  44. package/dist/file-picker.js +40 -0
  45. package/dist/file-picker.js.map +1 -0
  46. package/dist/forms-public.d.ts +8 -0
  47. package/dist/forms-public.d.ts.map +1 -0
  48. package/dist/forms-public.js +8 -0
  49. package/dist/forms-public.js.map +1 -0
  50. package/dist/forms.d.ts +160 -0
  51. package/dist/forms.d.ts.map +1 -0
  52. package/dist/forms.js +178 -0
  53. package/dist/forms.js.map +1 -0
  54. package/dist/index.d.ts +24 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +24 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/internal.d.ts +17 -0
  59. package/dist/internal.d.ts.map +1 -0
  60. package/dist/internal.js +68 -0
  61. package/dist/internal.js.map +1 -0
  62. package/dist/layout.d.ts +134 -0
  63. package/dist/layout.d.ts.map +1 -0
  64. package/dist/layout.js +167 -0
  65. package/dist/layout.js.map +1 -0
  66. package/dist/navigation-public.d.ts +6 -0
  67. package/dist/navigation-public.d.ts.map +1 -0
  68. package/dist/navigation-public.js +6 -0
  69. package/dist/navigation-public.js.map +1 -0
  70. package/dist/navigation.d.ts +65 -0
  71. package/dist/navigation.d.ts.map +1 -0
  72. package/dist/navigation.js +196 -0
  73. package/dist/navigation.js.map +1 -0
  74. package/dist/number-field.d.ts +55 -0
  75. package/dist/number-field.d.ts.map +1 -0
  76. package/dist/number-field.js +107 -0
  77. package/dist/number-field.js.map +1 -0
  78. package/dist/otp-field.d.ts +2 -0
  79. package/dist/otp-field.d.ts.map +1 -0
  80. package/dist/otp-field.js +2 -0
  81. package/dist/otp-field.js.map +1 -0
  82. package/dist/overlays.d.ts +192 -0
  83. package/dist/overlays.d.ts.map +1 -0
  84. package/dist/overlays.js +949 -0
  85. package/dist/overlays.js.map +1 -0
  86. package/dist/password-field.d.ts +2 -0
  87. package/dist/password-field.d.ts.map +1 -0
  88. package/dist/password-field.js +2 -0
  89. package/dist/password-field.js.map +1 -0
  90. package/dist/portal.d.ts +32 -0
  91. package/dist/portal.d.ts.map +1 -0
  92. package/dist/portal.js +264 -0
  93. package/dist/portal.js.map +1 -0
  94. package/dist/provider.d.ts +38 -0
  95. package/dist/provider.d.ts.map +1 -0
  96. package/dist/provider.js +87 -0
  97. package/dist/provider.js.map +1 -0
  98. package/dist/select.d.ts +72 -0
  99. package/dist/select.d.ts.map +1 -0
  100. package/dist/select.js +353 -0
  101. package/dist/select.js.map +1 -0
  102. package/dist/selection.d.ts +160 -0
  103. package/dist/selection.d.ts.map +1 -0
  104. package/dist/selection.js +225 -0
  105. package/dist/selection.js.map +1 -0
  106. package/dist/slider.d.ts +35 -0
  107. package/dist/slider.d.ts.map +1 -0
  108. package/dist/slider.js +150 -0
  109. package/dist/slider.js.map +1 -0
  110. package/dist/steps.d.ts +29 -0
  111. package/dist/steps.d.ts.map +1 -0
  112. package/dist/steps.js +10 -0
  113. package/dist/steps.js.map +1 -0
  114. package/dist/styles.css +1349 -0
  115. package/dist/supplemental-display.d.ts +59 -0
  116. package/dist/supplemental-display.d.ts.map +1 -0
  117. package/dist/supplemental-display.js +136 -0
  118. package/dist/supplemental-display.js.map +1 -0
  119. package/dist/supplemental-navigation.d.ts +28 -0
  120. package/dist/supplemental-navigation.d.ts.map +1 -0
  121. package/dist/supplemental-navigation.js +106 -0
  122. package/dist/supplemental-navigation.js.map +1 -0
  123. package/dist/theme.d.ts +5 -0
  124. package/dist/theme.d.ts.map +1 -0
  125. package/dist/theme.js +55 -0
  126. package/dist/theme.js.map +1 -0
  127. package/dist/toast.d.ts +41 -0
  128. package/dist/toast.d.ts.map +1 -0
  129. package/dist/toast.js +250 -0
  130. package/dist/toast.js.map +1 -0
  131. package/dist/upload-item.d.ts +18 -0
  132. package/dist/upload-item.d.ts.map +1 -0
  133. package/dist/upload-item.js +19 -0
  134. package/dist/upload-item.js.map +1 -0
  135. package/package.json +151 -0
@@ -0,0 +1,196 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { getTabNavigationIntent, getTabNavigationTarget, resolveInitialTabValue, tabsBehaviorDefaults, } from "@hjmds/design-contracts/behaviors";
3
+ import { iconRecipe, tabsRecipe, } from "@hjmds/design-contracts/recipes";
4
+ import { forwardRef, useEffect, useId, useRef, useState, } from "react";
5
+ import { classNames, useControllableState } from "./internal.js";
6
+ import { useOptionalHjmTheme } from "./provider.js";
7
+ function validateItems(items) {
8
+ if (items.length === 0)
9
+ throw new TypeError("Tabs requires at least one item");
10
+ const ids = new Set();
11
+ for (const item of items) {
12
+ if (item.id.trim().length === 0)
13
+ throw new TypeError("Tabs item id must not be empty");
14
+ if (ids.has(item.id))
15
+ throw new TypeError(`Duplicate Tabs item id: ${item.id}`);
16
+ ids.add(item.id);
17
+ }
18
+ if (!items.some((item) => !item.disabled)) {
19
+ throw new TypeError("Tabs requires at least one enabled item");
20
+ }
21
+ }
22
+ const panelFocusableSelector = [
23
+ "a[href]",
24
+ "button:not([disabled])",
25
+ "input:not([disabled])",
26
+ "select:not([disabled])",
27
+ "textarea:not([disabled])",
28
+ "[tabindex]:not([tabindex='-1'])",
29
+ ].join(",");
30
+ function TabPanelHost({ id, labelledBy, selected, dynamic, children, className, ...props }) {
31
+ const ref = useRef(null);
32
+ const [hasFocusableContent, setHasFocusableContent] = useState(false);
33
+ useEffect(() => {
34
+ setHasFocusableContent(ref.current?.querySelector(panelFocusableSelector) !== null);
35
+ }, [children]);
36
+ return (_jsx("div", { ...props, ref: ref, id: id, role: "tabpanel", className: classNames("hjm-tabs__panel", className), "aria-labelledby": labelledBy, tabIndex: selected && !hasFocusableContent ? 0 : undefined, hidden: !selected, inert: selected ? undefined : true, "data-state": selected ? "active" : "inactive", "data-panel-mode": dynamic ? "dynamic" : "keyed", children: children }));
37
+ }
38
+ function encodedTabId(value) {
39
+ return encodeURIComponent(value);
40
+ }
41
+ export function getTabId(tabsId, value) {
42
+ return `${tabsId}-tab-${encodedTabId(value)}`;
43
+ }
44
+ export function getTabPanelId(tabsId, value, mode = "keyed") {
45
+ return mode === "dynamic"
46
+ ? `${tabsId}-panel`
47
+ : `${tabsId}-panel-${encodedTabId(value)}`;
48
+ }
49
+ export function getDynamicTabPanelId(tabsId) {
50
+ return getTabPanelId(tabsId, "", "dynamic");
51
+ }
52
+ /** External panel host for products that keep routing, query, or scroll state outside Tabs. */
53
+ export function TabPanel(props) {
54
+ const { tabsId, activeValue, children } = props;
55
+ const dynamic = props.mode === "dynamic";
56
+ const value = dynamic ? activeValue : props.value;
57
+ const selected = value === activeValue;
58
+ const mountPolicy = dynamic ? "active" : props.mountPolicy ?? tabsBehaviorDefaults.mountPolicy;
59
+ let hostProps;
60
+ if (props.mode === "dynamic") {
61
+ const { tabsId: _tabsId, activeValue: _activeValue, children: _children, mode: _mode, ...htmlProps } = props;
62
+ hostProps = htmlProps;
63
+ }
64
+ else {
65
+ const { tabsId: _tabsId, activeValue: _activeValue, children: _children, mode: _mode, value: _value, mountPolicy: _mountPolicy, ...htmlProps } = props;
66
+ hostProps = htmlProps;
67
+ }
68
+ const [visited, setVisited] = useState(selected);
69
+ useEffect(() => {
70
+ if (selected)
71
+ setVisited(true);
72
+ }, [selected]);
73
+ const mounted = dynamic ||
74
+ selected ||
75
+ mountPolicy === "always" ||
76
+ (mountPolicy === "visited" && visited);
77
+ if (!mounted)
78
+ return null;
79
+ return (_jsx(TabPanelHost, { ...hostProps, id: getTabPanelId(tabsId, value, dynamic ? "dynamic" : "keyed"), labelledBy: getTabId(tabsId, dynamic ? activeValue : value), selected: selected, dynamic: dynamic, children: children }));
80
+ }
81
+ export const Tabs = forwardRef(function Tabs(props, ref) {
82
+ const { label, items, activationMode = tabsBehaviorDefaults.activationMode, mountPolicy = tabsBehaviorDefaults.mountPolicy, panelMode = tabsBehaviorDefaults.panelMode, orientation = tabsBehaviorDefaults.orientation, direction: directionProp, loop = tabsBehaviorDefaults.loop, size = tabsRecipe.defaults.size, layout = tabsRecipe.defaults.layout, overflow = tabsRecipe.defaults.overflow, renderPanels = true, className, id, value: valueProp, defaultValue, onValueChange, ...rest } = props;
83
+ validateItems(items);
84
+ if (label.trim().length === 0)
85
+ throw new TypeError("Tabs label must not be empty");
86
+ if (panelMode === "dynamic" && mountPolicy !== "active") {
87
+ throw new TypeError("Tabs dynamic panelMode requires active mountPolicy");
88
+ }
89
+ const descriptors = items.map((item) => ({
90
+ id: item.id,
91
+ label: item.id,
92
+ ...(item.disabled === undefined ? {} : { disabled: item.disabled }),
93
+ }));
94
+ const initialValueRef = useRef(null);
95
+ if (initialValueRef.current === null) {
96
+ const resolved = resolveInitialTabValue(descriptors, defaultValue);
97
+ if (resolved === undefined)
98
+ throw new TypeError("Tabs requires an enabled item");
99
+ initialValueRef.current = { value: resolved };
100
+ }
101
+ const initialValue = initialValueRef.current.value;
102
+ const collectionFallback = items.find((item) => !item.disabled)?.id;
103
+ if (collectionFallback === undefined)
104
+ throw new TypeError("Tabs requires an enabled item");
105
+ const [storedValue, setValue] = useControllableState({
106
+ ...(valueProp === undefined ? {} : { value: valueProp }),
107
+ defaultValue: initialValue,
108
+ ...(onValueChange === undefined ? {} : { onChange: onValueChange }),
109
+ });
110
+ const controlled = valueProp !== undefined;
111
+ const storedSelectionIsValid = items.some((item) => item.id === storedValue && !item.disabled);
112
+ if (controlled && !storedSelectionIsValid) {
113
+ throw new RangeError(`Tabs value must identify an enabled item: ${storedValue}`);
114
+ }
115
+ const value = storedSelectionIsValid ? storedValue : collectionFallback;
116
+ const [focusValue, setFocusValue] = useState(value);
117
+ const resolvedFocusValue = items.some((item) => item.id === focusValue && !item.disabled)
118
+ ? focusValue
119
+ : value;
120
+ const [visited, setVisited] = useState(() => new Set([value]));
121
+ const tabRefs = useRef(new Map());
122
+ const generatedId = useId().replaceAll(":", "");
123
+ const baseId = id ?? `hjm-${generatedId}`;
124
+ const theme = useOptionalHjmTheme();
125
+ const direction = directionProp ?? theme?.environment.direction ?? tabsBehaviorDefaults.direction;
126
+ useEffect(() => {
127
+ if (!controlled && !storedSelectionIsValid)
128
+ setValue(collectionFallback);
129
+ }, [collectionFallback, controlled, setValue, storedSelectionIsValid]);
130
+ useEffect(() => {
131
+ if (!items.some((item) => item.id === focusValue && !item.disabled)) {
132
+ setFocusValue(value);
133
+ }
134
+ }, [focusValue, items, value]);
135
+ useEffect(() => {
136
+ setVisited((current) => {
137
+ const known = new Set(items.map((item) => item.id));
138
+ const next = new Set([...current].filter((id) => known.has(id)));
139
+ next.add(value);
140
+ if (next.size === current.size &&
141
+ [...next].every((id) => current.has(id)))
142
+ return current;
143
+ return next;
144
+ });
145
+ }, [items, value]);
146
+ const focusItem = (id) => {
147
+ setFocusValue(id);
148
+ if (activationMode === "automatic")
149
+ setValue(id);
150
+ queueMicrotask(() => tabRefs.current.get(id)?.focus());
151
+ };
152
+ const handleKeyDown = (event, id) => {
153
+ const intent = getTabNavigationIntent(event.key === " " ? "Space" : event.key, orientation, direction);
154
+ if (intent !== undefined) {
155
+ const target = getTabNavigationTarget(descriptors, id, intent, loop);
156
+ if (target !== undefined) {
157
+ event.preventDefault();
158
+ focusItem(target);
159
+ }
160
+ return;
161
+ }
162
+ if (activationMode === "manual" &&
163
+ (event.key === "Enter" || event.key === " ")) {
164
+ event.preventDefault();
165
+ setValue(id);
166
+ }
167
+ };
168
+ const panelId = (value) => getTabPanelId(baseId, value, panelMode);
169
+ return (_jsxs("div", { ...rest, ref: ref, id: baseId, className: classNames("hjm-tabs", className), "data-size": size, "data-layout": layout, "data-overflow": overflow, "data-orientation": orientation, "data-mount-policy": mountPolicy, "data-panel-mode": panelMode, "data-state": "ready", dir: direction, children: [_jsx("div", { className: "hjm-tabs__list", role: "tablist", "aria-label": label, "aria-orientation": orientation, children: items.map((item) => {
170
+ const selected = item.id === value;
171
+ const tabId = getTabId(baseId, item.id);
172
+ const leadingSize = iconRecipe.sizes[tabsRecipe.icon.glyph];
173
+ return (_jsxs("button", { ref: (node) => {
174
+ if (node)
175
+ tabRefs.current.set(item.id, node);
176
+ else
177
+ tabRefs.current.delete(item.id);
178
+ }, id: tabId, type: "button", role: "tab", className: "hjm-tabs__tab", "data-state": selected ? "selected" : "idle", "aria-selected": selected, "aria-controls": panelId(item.id), tabIndex: item.id === resolvedFocusValue ? 0 : -1, disabled: item.disabled, onClick: () => {
179
+ setFocusValue(item.id);
180
+ setValue(item.id);
181
+ }, onKeyDown: (event) => handleKeyDown(event, item.id), children: [item.renderLeading ? (_jsx("span", { "aria-hidden": "true", className: "hjm-tabs__leading", children: item.renderLeading({
182
+ selected,
183
+ disabled: item.disabled ?? false,
184
+ color: "currentColor",
185
+ size: leadingSize,
186
+ glyphSize: leadingSize,
187
+ }) })) : null, item.label] }, item.id));
188
+ }) }), !renderPanels ? null : panelMode === "dynamic" ? (_jsx(TabPanelHost, { id: panelId(value), labelledBy: getTabId(baseId, value), selected: true, dynamic: true, children: items.find((item) => item.id === value)?.panel })) : items.map((item) => {
189
+ const selected = item.id === value;
190
+ const mounted = mountPolicy === "always" ||
191
+ (mountPolicy === "visited" && (visited.has(item.id) || selected)) ||
192
+ (mountPolicy === "active" && selected);
193
+ return mounted ? (_jsx(TabPanelHost, { id: panelId(item.id), labelledBy: getTabId(baseId, item.id), selected: selected, dynamic: false, children: item.panel }, item.id)) : null;
194
+ })] }));
195
+ });
196
+ //# sourceMappingURL=navigation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation.js","sourceRoot":"","sources":["../src/navigation.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n getTabNavigationIntent,\n getTabNavigationTarget,\n resolveInitialTabValue,\n tabsBehaviorDefaults,\n type TabsActivationMode,\n type TabsDirection,\n type TabsMountPolicy,\n type TabsOrientation,\n type TabsPanelMode,\n} from \"@hjmds/design-contracts/behaviors\";\nimport {\n iconRecipe,\n tabsRecipe,\n type TabSize,\n type TabsLayout,\n type TabsOverflow,\n} from \"@hjmds/design-contracts/recipes\";\nimport {\n forwardRef,\n useEffect,\n useId,\n useRef,\n useState,\n type HTMLAttributes,\n type KeyboardEvent,\n type ReactNode,\n} from \"react\";\nimport { classNames, useControllableState } from \"./internal.js\";\nimport { useOptionalHjmTheme } from \"./provider.js\";\n\nexport type TabLeadingRenderProps = Readonly<{\n selected: boolean;\n disabled: boolean;\n color: \"currentColor\";\n /** Pixel size resolved from `tabsRecipe.icon.glyph`. */\n size: number;\n /** Compatibility alias for product icon libraries that name this value explicitly. */\n glyphSize: number;\n}>;\n\nexport type TabItem = Readonly<{\n id: string;\n label: ReactNode;\n panel?: ReactNode;\n renderLeading?: (state: TabLeadingRenderProps) => ReactNode;\n disabled?: boolean;\n}>;\n\ntype TabsSelection =\n | Readonly<{\n value: string;\n defaultValue?: never;\n onValueChange(value: string): void;\n }>\n | Readonly<{\n value?: never;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n }>;\n\nexport type TabsProps = Omit<HTMLAttributes<HTMLDivElement>, \"dir\" | \"onChange\"> &\n TabsSelection &\n Readonly<{\n label: string;\n items: readonly TabItem[];\n activationMode?: TabsActivationMode;\n mountPolicy?: TabsMountPolicy;\n panelMode?: TabsPanelMode;\n orientation?: TabsOrientation;\n direction?: TabsDirection;\n loop?: boolean;\n size?: TabSize;\n layout?: TabsLayout;\n overflow?: TabsOverflow;\n /** Set false when panels are rendered separately with `TabPanel`. */\n renderPanels?: boolean;\n }>;\n\nfunction validateItems(items: readonly TabItem[]): void {\n if (items.length === 0) throw new TypeError(\"Tabs requires at least one item\");\n const ids = new Set<string>();\n for (const item of items) {\n if (item.id.trim().length === 0) throw new TypeError(\"Tabs item id must not be empty\");\n if (ids.has(item.id)) throw new TypeError(`Duplicate Tabs item id: ${item.id}`);\n ids.add(item.id);\n }\n if (!items.some((item) => !item.disabled)) {\n throw new TypeError(\"Tabs requires at least one enabled item\");\n }\n}\n\nconst panelFocusableSelector = [\n \"a[href]\",\n \"button:not([disabled])\",\n \"input:not([disabled])\",\n \"select:not([disabled])\",\n \"textarea:not([disabled])\",\n \"[tabindex]:not([tabindex='-1'])\",\n].join(\",\");\n\ntype TabPanelHostProps = HTMLAttributes<HTMLDivElement> & Readonly<{\n id: string;\n labelledBy: string;\n selected: boolean;\n dynamic: boolean;\n children: ReactNode;\n}>;\n\nfunction TabPanelHost({\n id,\n labelledBy,\n selected,\n dynamic,\n children,\n className,\n ...props\n}: TabPanelHostProps) {\n const ref = useRef<HTMLDivElement>(null);\n const [hasFocusableContent, setHasFocusableContent] = useState(false);\n useEffect(() => {\n setHasFocusableContent(\n ref.current?.querySelector(panelFocusableSelector) !== null,\n );\n }, [children]);\n\n return (\n <div\n {...props}\n ref={ref}\n id={id}\n role=\"tabpanel\"\n className={classNames(\"hjm-tabs__panel\", className)}\n aria-labelledby={labelledBy}\n tabIndex={selected && !hasFocusableContent ? 0 : undefined}\n hidden={!selected}\n inert={selected ? undefined : true}\n data-state={selected ? \"active\" : \"inactive\"}\n data-panel-mode={dynamic ? \"dynamic\" : \"keyed\"}\n >\n {children}\n </div>\n );\n}\n\nfunction encodedTabId(value: string): string {\n return encodeURIComponent(value);\n}\n\nexport function getTabId(tabsId: string, value: string): string {\n return `${tabsId}-tab-${encodedTabId(value)}`;\n}\n\nexport function getTabPanelId(\n tabsId: string,\n value: string,\n mode: TabsPanelMode = \"keyed\",\n): string {\n return mode === \"dynamic\"\n ? `${tabsId}-panel`\n : `${tabsId}-panel-${encodedTabId(value)}`;\n}\n\nexport function getDynamicTabPanelId(tabsId: string): string {\n return getTabPanelId(tabsId, \"\", \"dynamic\");\n}\n\ntype ExternalTabPanelBaseProps = Omit<HTMLAttributes<HTMLDivElement>, \"id\"> &\n Readonly<{\n tabsId: string;\n activeValue: string;\n children: ReactNode;\n }>;\n\nexport type TabPanelProps = ExternalTabPanelBaseProps &\n (\n | Readonly<{\n mode: \"dynamic\";\n value?: never;\n mountPolicy?: never;\n }>\n | Readonly<{\n mode?: \"keyed\";\n value: string;\n mountPolicy?: TabsMountPolicy;\n }>\n );\n\n/** External panel host for products that keep routing, query, or scroll state outside Tabs. */\nexport function TabPanel(props: TabPanelProps) {\n const { tabsId, activeValue, children } = props;\n const dynamic = props.mode === \"dynamic\";\n const value = dynamic ? activeValue : props.value;\n const selected = value === activeValue;\n const mountPolicy = dynamic ? \"active\" : props.mountPolicy ?? tabsBehaviorDefaults.mountPolicy;\n let hostProps: Omit<HTMLAttributes<HTMLDivElement>, \"id\">;\n if (props.mode === \"dynamic\") {\n const {\n tabsId: _tabsId,\n activeValue: _activeValue,\n children: _children,\n mode: _mode,\n ...htmlProps\n } = props;\n hostProps = htmlProps;\n } else {\n const {\n tabsId: _tabsId,\n activeValue: _activeValue,\n children: _children,\n mode: _mode,\n value: _value,\n mountPolicy: _mountPolicy,\n ...htmlProps\n } = props;\n hostProps = htmlProps;\n }\n const [visited, setVisited] = useState(selected);\n useEffect(() => {\n if (selected) setVisited(true);\n }, [selected]);\n const mounted =\n dynamic ||\n selected ||\n mountPolicy === \"always\" ||\n (mountPolicy === \"visited\" && visited);\n if (!mounted) return null;\n return (\n <TabPanelHost\n {...hostProps}\n id={getTabPanelId(tabsId, value, dynamic ? \"dynamic\" : \"keyed\")}\n labelledBy={getTabId(tabsId, dynamic ? activeValue : value)}\n selected={selected}\n dynamic={dynamic}\n >\n {children}\n </TabPanelHost>\n );\n}\n\nexport const Tabs = forwardRef<HTMLDivElement, TabsProps>(function Tabs(\n props,\n ref,\n) {\n const {\n label,\n items,\n activationMode = tabsBehaviorDefaults.activationMode,\n mountPolicy = tabsBehaviorDefaults.mountPolicy,\n panelMode = tabsBehaviorDefaults.panelMode,\n orientation = tabsBehaviorDefaults.orientation,\n direction: directionProp,\n loop = tabsBehaviorDefaults.loop,\n size = tabsRecipe.defaults.size,\n layout = tabsRecipe.defaults.layout,\n overflow = tabsRecipe.defaults.overflow,\n renderPanels = true,\n className,\n id,\n value: valueProp,\n defaultValue,\n onValueChange,\n ...rest\n } = props;\n validateItems(items);\n if (label.trim().length === 0) throw new TypeError(\"Tabs label must not be empty\");\n if (panelMode === \"dynamic\" && mountPolicy !== \"active\") {\n throw new TypeError(\"Tabs dynamic panelMode requires active mountPolicy\");\n }\n const descriptors = items.map((item) => ({\n id: item.id,\n label: item.id,\n ...(item.disabled === undefined ? {} : { disabled: item.disabled }),\n }));\n const initialValueRef = useRef<Readonly<{ value: string }> | null>(null);\n if (initialValueRef.current === null) {\n const resolved = resolveInitialTabValue(descriptors, defaultValue);\n if (resolved === undefined) throw new TypeError(\"Tabs requires an enabled item\");\n initialValueRef.current = { value: resolved };\n }\n const initialValue = initialValueRef.current.value;\n const collectionFallback = items.find((item) => !item.disabled)?.id;\n if (collectionFallback === undefined) throw new TypeError(\"Tabs requires an enabled item\");\n const [storedValue, setValue] = useControllableState({\n ...(valueProp === undefined ? {} : { value: valueProp }),\n defaultValue: initialValue,\n ...(onValueChange === undefined ? {} : { onChange: onValueChange }),\n });\n const controlled = valueProp !== undefined;\n const storedSelectionIsValid = items.some(\n (item) => item.id === storedValue && !item.disabled,\n );\n if (controlled && !storedSelectionIsValid) {\n throw new RangeError(`Tabs value must identify an enabled item: ${storedValue}`);\n }\n const value = storedSelectionIsValid ? storedValue : collectionFallback;\n const [focusValue, setFocusValue] = useState(value);\n const resolvedFocusValue = items.some(\n (item) => item.id === focusValue && !item.disabled,\n )\n ? focusValue\n : value;\n const [visited, setVisited] = useState<ReadonlySet<string>>(() => new Set([value]));\n const tabRefs = useRef(new Map<string, HTMLButtonElement>());\n const generatedId = useId().replaceAll(\":\", \"\");\n const baseId = id ?? `hjm-${generatedId}`;\n const theme = useOptionalHjmTheme();\n const direction = directionProp ?? theme?.environment.direction ?? tabsBehaviorDefaults.direction;\n\n useEffect(() => {\n if (!controlled && !storedSelectionIsValid) setValue(collectionFallback);\n }, [collectionFallback, controlled, setValue, storedSelectionIsValid]);\n useEffect(() => {\n if (!items.some((item) => item.id === focusValue && !item.disabled)) {\n setFocusValue(value);\n }\n }, [focusValue, items, value]);\n useEffect(() => {\n setVisited((current) => {\n const known = new Set(items.map((item) => item.id));\n const next = new Set([...current].filter((id) => known.has(id)));\n next.add(value);\n if (\n next.size === current.size &&\n [...next].every((id) => current.has(id))\n ) return current;\n return next;\n });\n }, [items, value]);\n\n const focusItem = (id: string) => {\n setFocusValue(id);\n if (activationMode === \"automatic\") setValue(id);\n queueMicrotask(() => tabRefs.current.get(id)?.focus());\n };\n const handleKeyDown = (event: KeyboardEvent<HTMLButtonElement>, id: string) => {\n const intent = getTabNavigationIntent(\n event.key === \" \" ? \"Space\" : event.key as Parameters<typeof getTabNavigationIntent>[0],\n orientation,\n direction,\n );\n if (intent !== undefined) {\n const target = getTabNavigationTarget(descriptors, id, intent, loop);\n if (target !== undefined) {\n event.preventDefault();\n focusItem(target);\n }\n return;\n }\n if (\n activationMode === \"manual\" &&\n (event.key === \"Enter\" || event.key === \" \")\n ) {\n event.preventDefault();\n setValue(id);\n }\n };\n const panelId = (value: string) => getTabPanelId(baseId, value, panelMode);\n\n return (\n <div\n {...rest}\n ref={ref}\n id={baseId}\n className={classNames(\"hjm-tabs\", className)}\n data-size={size}\n data-layout={layout}\n data-overflow={overflow}\n data-orientation={orientation}\n data-mount-policy={mountPolicy}\n data-panel-mode={panelMode}\n data-state=\"ready\"\n dir={direction}\n >\n <div\n className=\"hjm-tabs__list\"\n role=\"tablist\"\n aria-label={label}\n aria-orientation={orientation}\n >\n {items.map((item) => {\n const selected = item.id === value;\n const tabId = getTabId(baseId, item.id);\n const leadingSize = iconRecipe.sizes[tabsRecipe.icon.glyph];\n return (\n <button\n key={item.id}\n ref={(node) => {\n if (node) tabRefs.current.set(item.id, node);\n else tabRefs.current.delete(item.id);\n }}\n id={tabId}\n type=\"button\"\n role=\"tab\"\n className=\"hjm-tabs__tab\"\n data-state={selected ? \"selected\" : \"idle\"}\n aria-selected={selected}\n aria-controls={panelId(item.id)}\n tabIndex={item.id === resolvedFocusValue ? 0 : -1}\n disabled={item.disabled}\n onClick={() => {\n setFocusValue(item.id);\n setValue(item.id);\n }}\n onKeyDown={(event) => handleKeyDown(event, item.id)}\n >\n {item.renderLeading ? (\n <span aria-hidden=\"true\" className=\"hjm-tabs__leading\">\n {item.renderLeading({\n selected,\n disabled: item.disabled ?? false,\n color: \"currentColor\",\n size: leadingSize,\n glyphSize: leadingSize,\n })}\n </span>\n ) : null}\n {item.label}\n </button>\n );\n })}\n </div>\n {!renderPanels ? null : panelMode === \"dynamic\" ? (\n <TabPanelHost\n id={panelId(value)}\n labelledBy={getTabId(baseId, value)}\n selected\n dynamic\n >\n {items.find((item) => item.id === value)?.panel}\n </TabPanelHost>\n ) : items.map((item) => {\n const selected = item.id === value;\n const mounted = mountPolicy === \"always\" ||\n (mountPolicy === \"visited\" && (visited.has(item.id) || selected)) ||\n (mountPolicy === \"active\" && selected);\n return mounted ? (\n <TabPanelHost\n key={item.id}\n id={panelId(item.id)}\n labelledBy={getTabId(baseId, item.id)}\n selected={selected}\n dynamic={false}\n >\n {item.panel}\n </TabPanelHost>\n ) : null;\n })}\n </div>\n );\n});\n"]}
@@ -0,0 +1,55 @@
1
+ import { type NumberFieldSize, type NumberFieldValue } from "@hjmds/design-contracts/components/number-field";
2
+ import { type InputHTMLAttributes, type ReactNode } from "react";
3
+ type NativeNumberInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "aria-errormessage" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "children" | "className" | "defaultValue" | "disabled" | "max" | "min" | "onChange" | "readOnly" | "required" | "role" | "size" | "step" | "type" | "value">;
4
+ export type NumberFieldProps = NativeNumberInputProps & Readonly<{
5
+ label: ReactNode;
6
+ min: number;
7
+ max: number;
8
+ step?: number;
9
+ value?: NumberFieldValue;
10
+ defaultValue?: NumberFieldValue;
11
+ onValueChange?: (value: NumberFieldValue) => void;
12
+ description?: ReactNode;
13
+ error?: ReactNode;
14
+ required?: boolean;
15
+ disabled?: boolean;
16
+ readOnly?: boolean;
17
+ size?: NumberFieldSize;
18
+ /** Product-localized accessible name for the decrement action. */
19
+ decrementLabel: string;
20
+ /** Product-localized accessible name for the increment action. */
21
+ incrementLabel: string;
22
+ /** Optional product formatting for assistive output, never the editable text. */
23
+ getValueText?: (value: number) => string;
24
+ className?: string;
25
+ inputClassName?: string;
26
+ }>;
27
+ /**
28
+ * Exact numeric entry with a nullable draft and explicit single-step actions.
29
+ * Typing commits on blur; steppers and ArrowUp/ArrowDown commit immediately.
30
+ */
31
+ export declare const NumberField: import("react").ForwardRefExoticComponent<NativeNumberInputProps & Readonly<{
32
+ label: ReactNode;
33
+ min: number;
34
+ max: number;
35
+ step?: number;
36
+ value?: NumberFieldValue;
37
+ defaultValue?: NumberFieldValue;
38
+ onValueChange?: (value: NumberFieldValue) => void;
39
+ description?: ReactNode;
40
+ error?: ReactNode;
41
+ required?: boolean;
42
+ disabled?: boolean;
43
+ readOnly?: boolean;
44
+ size?: NumberFieldSize;
45
+ /** Product-localized accessible name for the decrement action. */
46
+ decrementLabel: string;
47
+ /** Product-localized accessible name for the increment action. */
48
+ incrementLabel: string;
49
+ /** Optional product formatting for assistive output, never the editable text. */
50
+ getValueText?: (value: number) => string;
51
+ className?: string;
52
+ inputClassName?: string;
53
+ }> & import("react").RefAttributes<HTMLInputElement>>;
54
+ export {};
55
+ //# sourceMappingURL=number-field.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number-field.d.ts","sourceRoot":"","sources":["../src/number-field.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAOL,KAAK,mBAAmB,EAExB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,KAAK,sBAAsB,GAAG,IAAI,CAChC,mBAAmB,CAAC,gBAAgB,CAAC,EACnC,mBAAmB,GACnB,eAAe,GACf,eAAe,GACf,eAAe,GACf,gBAAgB,GAChB,UAAU,GACV,WAAW,GACX,cAAc,GACd,UAAU,GACV,KAAK,GACL,KAAK,GACL,UAAU,GACV,UAAU,GACV,UAAU,GACV,MAAM,GACN,MAAM,GACN,MAAM,GACN,MAAM,GACN,OAAO,CACV,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,sBAAsB,GACnD,QAAQ,CAAC;IACP,KAAK,EAAE,SAAS,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,kEAAkE;IAClE,cAAc,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,cAAc,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC,CAAC;AAWL;;;GAGG;AACH,eAAO,MAAM,WAAW;WApCb,SAAS;SACX,MAAM;SACN,MAAM;WACJ,MAAM;YACL,gBAAgB;mBACT,gBAAgB;oBACf,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI;kBACnC,SAAS;YACf,SAAS;eACN,OAAO;eACP,OAAO;eACP,OAAO;WACX,eAAe;IACtB,kEAAkE;oBAClD,MAAM;IACtB,kEAAkE;oBAClD,MAAM;IACtB,iFAAiF;mBAClE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM;gBAC5B,MAAM;qBACD,MAAM;qDAuN1B,CAAC"}
@@ -0,0 +1,107 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { commitNumberFieldInput, parseNumberFieldInput, resolveNumberFieldDescriptor, resolveNumberFieldInputStepperState, stepNumberFieldInput, } from "@hjmds/design-contracts/components/number-field";
3
+ import { forwardRef, useEffect, useId, useRef, useState, } from "react";
4
+ import { classNames, composeRefs, useControllableState } from "./internal.js";
5
+ function valueToInput(value) {
6
+ return value === null ? "" : String(value);
7
+ }
8
+ function defaultInputMode(min, step) {
9
+ if (min < 0)
10
+ return "text";
11
+ return Number.isInteger(step) ? "numeric" : "decimal";
12
+ }
13
+ /**
14
+ * Exact numeric entry with a nullable draft and explicit single-step actions.
15
+ * Typing commits on blur; steppers and ArrowUp/ArrowDown commit immediately.
16
+ */
17
+ export const NumberField = forwardRef(function NumberField({ id, label, min, max, step, value, defaultValue = null, onValueChange, description, error, required = false, disabled = false, readOnly = false, size = "medium", decrementLabel, incrementLabel, getValueText, className, inputClassName, inputMode, onBlur, onFocus, onKeyDown, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, ...inputProps }, forwardedRef) {
18
+ const generatedId = useId();
19
+ const controlId = id ?? `hjm-number-${generatedId.replaceAll(":", "")}`;
20
+ const descriptionId = `${controlId}-description`;
21
+ const errorId = `${controlId}-error`;
22
+ const inputRef = useRef(null);
23
+ const controlled = value !== undefined;
24
+ const controlledAtMount = useRef(controlled);
25
+ if (controlledAtMount.current !== controlled) {
26
+ throw new Error("HJM components cannot switch between controlled and uncontrolled state");
27
+ }
28
+ const [currentValue, setCurrentValue] = useControllableState({
29
+ ...(controlled ? { value } : {}),
30
+ defaultValue,
31
+ ...(onValueChange === undefined ? {} : { onChange: onValueChange }),
32
+ });
33
+ const descriptor = resolveNumberFieldDescriptor({
34
+ value: currentValue,
35
+ min,
36
+ max,
37
+ ...(step === undefined ? {} : { step }),
38
+ });
39
+ const [draft, setDraft] = useState(() => valueToInput(currentValue));
40
+ const [focused, setFocused] = useState(false);
41
+ const stepper = resolveNumberFieldInputStepperState(draft, descriptor);
42
+ useEffect(() => {
43
+ setDraft(valueToInput(currentValue));
44
+ }, [currentValue]);
45
+ const restoreOrDisplay = (next) => {
46
+ setDraft(valueToInput(controlled ? currentValue : next));
47
+ };
48
+ const commitDraft = () => {
49
+ const next = commitNumberFieldInput(draft, descriptor);
50
+ if (next === undefined) {
51
+ setDraft(valueToInput(currentValue));
52
+ return;
53
+ }
54
+ if (!Object.is(next, currentValue))
55
+ setCurrentValue(next);
56
+ restoreOrDisplay(next);
57
+ };
58
+ const stepValue = (direction) => {
59
+ if (disabled || readOnly)
60
+ return;
61
+ const next = stepNumberFieldInput(draft, descriptor, direction);
62
+ if (!Object.is(next, currentValue))
63
+ setCurrentValue(next);
64
+ restoreOrDisplay(next);
65
+ inputRef.current?.focus({ preventScroll: true });
66
+ };
67
+ const handleFocus = (event) => {
68
+ setFocused(true);
69
+ onFocus?.(event);
70
+ };
71
+ const handleBlur = (event) => {
72
+ setFocused(false);
73
+ commitDraft();
74
+ onBlur?.(event);
75
+ };
76
+ const handleKeyDown = (event) => {
77
+ onKeyDown?.(event);
78
+ if (event.defaultPrevented || disabled || readOnly)
79
+ return;
80
+ if (event.key === "ArrowUp" || event.key === "ArrowDown") {
81
+ event.preventDefault();
82
+ stepValue(event.key === "ArrowUp" ? "increment" : "decrement");
83
+ }
84
+ else if (event.key === "Enter") {
85
+ commitDraft();
86
+ }
87
+ };
88
+ const unavailable = disabled || readOnly;
89
+ const state = disabled
90
+ ? "disabled"
91
+ : error || ariaInvalid
92
+ ? "invalid"
93
+ : focused
94
+ ? "focused"
95
+ : "idle";
96
+ const describedBy = [
97
+ ariaDescribedBy,
98
+ error ? errorId : description ? descriptionId : undefined,
99
+ ].filter(Boolean).join(" ") || undefined;
100
+ const parsedDraft = parseNumberFieldInput(draft);
101
+ const announcedValue = typeof parsedDraft === "number" && parsedDraft >= min && parsedDraft <= max
102
+ ? parsedDraft
103
+ : currentValue;
104
+ const valueText = announcedValue === null ? undefined : getValueText?.(announcedValue);
105
+ return (_jsxs("div", { className: classNames("hjm-field", "hjm-number-field", className), "data-availability": disabled ? "disabled" : readOnly ? "readOnly" : "enabled", "data-size": size, "data-state": state, "data-value": currentValue === null ? "empty" : "filled", children: [_jsxs("label", { className: "hjm-field__label", htmlFor: controlId, children: [label, required ? _jsx("span", { "aria-hidden": "true", children: " *" }) : null] }), _jsxs("div", { className: "hjm-field__control hjm-number-field__control", children: [_jsx("button", { type: "button", "aria-controls": controlId, "aria-label": decrementLabel, className: "hjm-number-field__stepper", "data-direction": "decrement", disabled: unavailable || stepper.decrementDisabled, onClick: () => stepValue("decrement"), onMouseDown: (event) => event.preventDefault(), tabIndex: -1, children: _jsx("span", { "aria-hidden": "true", children: "\u2212" }) }), _jsx("input", { ...inputProps, ref: composeRefs(inputRef, forwardedRef), id: controlId, type: "text", role: "spinbutton", className: classNames("hjm-field__input", "hjm-number-field__input", inputClassName), value: draft, inputMode: inputMode ?? defaultInputMode(min, descriptor.step), required: required, disabled: disabled, readOnly: readOnly, "aria-invalid": error ? true : ariaInvalid, "aria-describedby": describedBy, ...(error ? { "aria-errormessage": errorId } : {}), "aria-valuemin": min, "aria-valuemax": max, ...(announcedValue === null ? {} : { "aria-valuenow": announcedValue }), ...(valueText === undefined ? {} : { "aria-valuetext": valueText }), onChange: (event) => setDraft(event.currentTarget.value), onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown }), _jsx("button", { type: "button", "aria-controls": controlId, "aria-label": incrementLabel, className: "hjm-number-field__stepper", "data-direction": "increment", disabled: unavailable || stepper.incrementDisabled, onClick: () => stepValue("increment"), onMouseDown: (event) => event.preventDefault(), tabIndex: -1, children: _jsx("span", { "aria-hidden": "true", children: "+" }) })] }), description && !error ? (_jsx("div", { id: descriptionId, className: "hjm-field__description", children: description })) : null, error ? (_jsx("div", { id: errorId, className: "hjm-field__error", children: error })) : null] }));
106
+ });
107
+ //# sourceMappingURL=number-field.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number-field.js","sourceRoot":"","sources":["../src/number-field.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n commitNumberFieldInput,\n parseNumberFieldInput,\n resolveNumberFieldDescriptor,\n resolveNumberFieldInputStepperState,\n stepNumberFieldInput,\n type NumberFieldSize,\n type NumberFieldValue,\n} from \"@hjmds/design-contracts/components/number-field\";\nimport {\n forwardRef,\n useEffect,\n useId,\n useRef,\n useState,\n type FocusEvent,\n type InputHTMLAttributes,\n type KeyboardEvent,\n type ReactNode,\n} from \"react\";\n\nimport { classNames, composeRefs, useControllableState } from \"./internal.js\";\n\ntype NativeNumberInputProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n | \"aria-errormessage\"\n | \"aria-valuemax\"\n | \"aria-valuemin\"\n | \"aria-valuenow\"\n | \"aria-valuetext\"\n | \"children\"\n | \"className\"\n | \"defaultValue\"\n | \"disabled\"\n | \"max\"\n | \"min\"\n | \"onChange\"\n | \"readOnly\"\n | \"required\"\n | \"role\"\n | \"size\"\n | \"step\"\n | \"type\"\n | \"value\"\n>;\n\nexport type NumberFieldProps = NativeNumberInputProps &\n Readonly<{\n label: ReactNode;\n min: number;\n max: number;\n step?: number;\n value?: NumberFieldValue;\n defaultValue?: NumberFieldValue;\n onValueChange?: (value: NumberFieldValue) => void;\n description?: ReactNode;\n error?: ReactNode;\n required?: boolean;\n disabled?: boolean;\n readOnly?: boolean;\n size?: NumberFieldSize;\n /** Product-localized accessible name for the decrement action. */\n decrementLabel: string;\n /** Product-localized accessible name for the increment action. */\n incrementLabel: string;\n /** Optional product formatting for assistive output, never the editable text. */\n getValueText?: (value: number) => string;\n className?: string;\n inputClassName?: string;\n }>;\n\nfunction valueToInput(value: NumberFieldValue): string {\n return value === null ? \"\" : String(value);\n}\n\nfunction defaultInputMode(min: number, step: number): \"decimal\" | \"numeric\" | \"text\" {\n if (min < 0) return \"text\";\n return Number.isInteger(step) ? \"numeric\" : \"decimal\";\n}\n\n/**\n * Exact numeric entry with a nullable draft and explicit single-step actions.\n * Typing commits on blur; steppers and ArrowUp/ArrowDown commit immediately.\n */\nexport const NumberField = forwardRef<HTMLInputElement, NumberFieldProps>(\n function NumberField(\n {\n id,\n label,\n min,\n max,\n step,\n value,\n defaultValue = null,\n onValueChange,\n description,\n error,\n required = false,\n disabled = false,\n readOnly = false,\n size = \"medium\",\n decrementLabel,\n incrementLabel,\n getValueText,\n className,\n inputClassName,\n inputMode,\n onBlur,\n onFocus,\n onKeyDown,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-invalid\": ariaInvalid,\n ...inputProps\n },\n forwardedRef,\n ) {\n const generatedId = useId();\n const controlId = id ?? `hjm-number-${generatedId.replaceAll(\":\", \"\")}`;\n const descriptionId = `${controlId}-description`;\n const errorId = `${controlId}-error`;\n const inputRef = useRef<HTMLInputElement>(null);\n const controlled = value !== undefined;\n const controlledAtMount = useRef(controlled);\n if (controlledAtMount.current !== controlled) {\n throw new Error(\"HJM components cannot switch between controlled and uncontrolled state\");\n }\n const [currentValue, setCurrentValue] = useControllableState<NumberFieldValue>({\n ...(controlled ? { value } : {}),\n defaultValue,\n ...(onValueChange === undefined ? {} : { onChange: onValueChange }),\n });\n const descriptor = resolveNumberFieldDescriptor({\n value: currentValue,\n min,\n max,\n ...(step === undefined ? {} : { step }),\n });\n const [draft, setDraft] = useState(() => valueToInput(currentValue));\n const [focused, setFocused] = useState(false);\n const stepper = resolveNumberFieldInputStepperState(draft, descriptor);\n\n useEffect(() => {\n setDraft(valueToInput(currentValue));\n }, [currentValue]);\n\n const restoreOrDisplay = (next: NumberFieldValue) => {\n setDraft(valueToInput(controlled ? currentValue : next));\n };\n\n const commitDraft = () => {\n const next = commitNumberFieldInput(draft, descriptor);\n if (next === undefined) {\n setDraft(valueToInput(currentValue));\n return;\n }\n if (!Object.is(next, currentValue)) setCurrentValue(next);\n restoreOrDisplay(next);\n };\n\n const stepValue = (direction: \"increment\" | \"decrement\") => {\n if (disabled || readOnly) return;\n const next = stepNumberFieldInput(draft, descriptor, direction);\n if (!Object.is(next, currentValue)) setCurrentValue(next);\n restoreOrDisplay(next);\n inputRef.current?.focus({ preventScroll: true });\n };\n\n const handleFocus = (event: FocusEvent<HTMLInputElement>) => {\n setFocused(true);\n onFocus?.(event);\n };\n const handleBlur = (event: FocusEvent<HTMLInputElement>) => {\n setFocused(false);\n commitDraft();\n onBlur?.(event);\n };\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented || disabled || readOnly) return;\n if (event.key === \"ArrowUp\" || event.key === \"ArrowDown\") {\n event.preventDefault();\n stepValue(event.key === \"ArrowUp\" ? \"increment\" : \"decrement\");\n } else if (event.key === \"Enter\") {\n commitDraft();\n }\n };\n\n const unavailable = disabled || readOnly;\n const state = disabled\n ? \"disabled\"\n : error || ariaInvalid\n ? \"invalid\"\n : focused\n ? \"focused\"\n : \"idle\";\n const describedBy = [\n ariaDescribedBy,\n error ? errorId : description ? descriptionId : undefined,\n ].filter(Boolean).join(\" \") || undefined;\n const parsedDraft = parseNumberFieldInput(draft);\n const announcedValue =\n typeof parsedDraft === \"number\" && parsedDraft >= min && parsedDraft <= max\n ? parsedDraft\n : currentValue;\n const valueText = announcedValue === null ? undefined : getValueText?.(announcedValue);\n\n return (\n <div\n className={classNames(\"hjm-field\", \"hjm-number-field\", className)}\n data-availability={disabled ? \"disabled\" : readOnly ? \"readOnly\" : \"enabled\"}\n data-size={size}\n data-state={state}\n data-value={currentValue === null ? \"empty\" : \"filled\"}\n >\n <label className=\"hjm-field__label\" htmlFor={controlId}>\n {label}\n {required ? <span aria-hidden=\"true\"> *</span> : null}\n </label>\n <div className=\"hjm-field__control hjm-number-field__control\">\n <button\n type=\"button\"\n aria-controls={controlId}\n aria-label={decrementLabel}\n className=\"hjm-number-field__stepper\"\n data-direction=\"decrement\"\n disabled={unavailable || stepper.decrementDisabled}\n onClick={() => stepValue(\"decrement\")}\n onMouseDown={(event) => event.preventDefault()}\n tabIndex={-1}\n >\n <span aria-hidden=\"true\">−</span>\n </button>\n <input\n {...inputProps}\n ref={composeRefs(inputRef, forwardedRef)}\n id={controlId}\n type=\"text\"\n role=\"spinbutton\"\n className={classNames(\n \"hjm-field__input\",\n \"hjm-number-field__input\",\n inputClassName,\n )}\n value={draft}\n inputMode={inputMode ?? defaultInputMode(min, descriptor.step)}\n required={required}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={error ? true : ariaInvalid}\n aria-describedby={describedBy}\n {...(error ? { \"aria-errormessage\": errorId } : {})}\n aria-valuemin={min}\n aria-valuemax={max}\n {...(announcedValue === null ? {} : { \"aria-valuenow\": announcedValue })}\n {...(valueText === undefined ? {} : { \"aria-valuetext\": valueText })}\n onChange={(event) => setDraft(event.currentTarget.value)}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n />\n <button\n type=\"button\"\n aria-controls={controlId}\n aria-label={incrementLabel}\n className=\"hjm-number-field__stepper\"\n data-direction=\"increment\"\n disabled={unavailable || stepper.incrementDisabled}\n onClick={() => stepValue(\"increment\")}\n onMouseDown={(event) => event.preventDefault()}\n tabIndex={-1}\n >\n <span aria-hidden=\"true\">+</span>\n </button>\n </div>\n {description && !error ? (\n <div id={descriptionId} className=\"hjm-field__description\">{description}</div>\n ) : null}\n {error ? (\n <div id={errorId} className=\"hjm-field__error\">{error}</div>\n ) : null}\n </div>\n );\n },\n);\n"]}
@@ -0,0 +1,2 @@
1
+ export { OtpField, type OtpFieldProps } from "./forms.js";
2
+ //# sourceMappingURL=otp-field.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otp-field.d.ts","sourceRoot":"","sources":["../src/otp-field.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { OtpField } from "./forms.js";
2
+ //# sourceMappingURL=otp-field.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otp-field.js","sourceRoot":"","sources":["../src/otp-field.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAsB,MAAM,YAAY,CAAC","sourcesContent":["export { OtpField, type OtpFieldProps } from \"./forms.js\";\n"]}