@tensor_1/react 2.46.0 → 2.48.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 (204) hide show
  1. package/README.md +509 -1
  2. package/dist/{SchedulingCalendar-B6TakO2h.d.ts → SchedulingCalendar-WWyFL3Eo.d.ts} +51 -2
  3. package/dist/announce.d.ts +10 -0
  4. package/dist/announce.js +30 -0
  5. package/dist/chart-analytic.cjs +33 -25
  6. package/dist/chart-preset.cjs +23 -15
  7. package/dist/chart.cjs +23 -15
  8. package/dist/combobox-model.d.ts +10 -1
  9. package/dist/combobox-model.js +15 -0
  10. package/dist/command-palette-model.d.ts +44 -0
  11. package/dist/command-palette-model.js +36 -0
  12. package/dist/components/AccountMenu.d.ts +44 -0
  13. package/dist/components/AccountMenu.js +43 -0
  14. package/dist/components/AppShell.d.ts +45 -2
  15. package/dist/components/AppShell.js +116 -5
  16. package/dist/components/AuditLog.d.ts +128 -0
  17. package/dist/components/AuditLog.js +196 -0
  18. package/dist/components/BrandProfiles.js +4 -3
  19. package/dist/components/Breadcrumbs.d.ts +9 -2
  20. package/dist/components/Breadcrumbs.js +3 -2
  21. package/dist/components/BusyBar.d.ts +13 -0
  22. package/dist/components/BusyBar.js +10 -0
  23. package/dist/components/BusyRegion.d.ts +18 -0
  24. package/dist/components/BusyRegion.js +12 -0
  25. package/dist/components/Button.d.ts +33 -5
  26. package/dist/components/Button.js +12 -6
  27. package/dist/components/ButtonFeedback.d.ts +30 -0
  28. package/dist/components/ButtonFeedback.js +78 -0
  29. package/dist/components/Card.d.ts +18 -1
  30. package/dist/components/Card.js +5 -1
  31. package/dist/components/ChangeHighlight.d.ts +30 -0
  32. package/dist/components/ChangeHighlight.js +21 -0
  33. package/dist/components/ChartCore.js +2 -1
  34. package/dist/components/Checkbox.d.ts +27 -1
  35. package/dist/components/Checkbox.js +31 -2
  36. package/dist/components/CodeDisplay.d.ts +65 -0
  37. package/dist/components/CodeDisplay.js +124 -0
  38. package/dist/components/Combobox.d.ts +27 -6
  39. package/dist/components/Combobox.js +195 -58
  40. package/dist/components/CommandPalette.d.ts +36 -1
  41. package/dist/components/CommandPalette.js +254 -2
  42. package/dist/components/ContactCard.d.ts +66 -0
  43. package/dist/components/ContactCard.js +74 -0
  44. package/dist/components/Count.d.ts +24 -0
  45. package/dist/components/Count.js +32 -0
  46. package/dist/components/DataWorkspace.d.ts +167 -0
  47. package/dist/components/DataWorkspace.js +383 -0
  48. package/dist/components/DateFieldParts.d.ts +2 -1
  49. package/dist/components/DateFieldParts.js +7 -0
  50. package/dist/components/DatePicker.d.ts +9 -2
  51. package/dist/components/DatePicker.js +67 -28
  52. package/dist/components/DateRangePicker.d.ts +12 -2
  53. package/dist/components/DateRangePicker.js +13 -12
  54. package/dist/components/DelayedRender.d.ts +15 -0
  55. package/dist/components/DelayedRender.js +10 -0
  56. package/dist/components/DetailPage.d.ts +7 -1
  57. package/dist/components/DetailPage.js +2 -1
  58. package/dist/components/Dialogs.d.ts +71 -10
  59. package/dist/components/Dialogs.js +130 -30
  60. package/dist/components/DiffViewer.d.ts +23 -3
  61. package/dist/components/DiffViewer.js +26 -12
  62. package/dist/components/DiscardPrompt.d.ts +1 -0
  63. package/dist/components/DiscardPrompt.js +16 -0
  64. package/dist/components/DisplayPreferences.d.ts +83 -0
  65. package/dist/components/DisplayPreferences.js +185 -0
  66. package/dist/components/Drawer.d.ts +1 -0
  67. package/dist/components/EditorialHome.d.ts +23 -3
  68. package/dist/components/EditorialHome.js +16 -11
  69. package/dist/components/EntityPicker.d.ts +20 -3
  70. package/dist/components/EntityPicker.js +32 -13
  71. package/dist/components/FilterEditor.d.ts +18 -4
  72. package/dist/components/FilterEditor.js +141 -19
  73. package/dist/components/InfoTip.js +11 -12
  74. package/dist/components/InlineEdit.d.ts +87 -20
  75. package/dist/components/InlineEdit.js +197 -54
  76. package/dist/components/Input.d.ts +12 -2
  77. package/dist/components/Input.js +5 -3
  78. package/dist/components/Kbd.d.ts +6 -1
  79. package/dist/components/Kbd.js +6 -6
  80. package/dist/components/Lightbox.d.ts +41 -5
  81. package/dist/components/Lightbox.js +95 -9
  82. package/dist/components/MatchReview.d.ts +40 -1
  83. package/dist/components/MatchReview.js +130 -4
  84. package/dist/components/MetricInput.js +3 -2
  85. package/dist/components/Modal.d.ts +3 -1
  86. package/dist/components/Modal.js +13 -4
  87. package/dist/components/NavFavourites.d.ts +5 -0
  88. package/dist/components/NavFavourites.js +7 -7
  89. package/dist/components/OtpInput.d.ts +33 -0
  90. package/dist/components/OtpInput.js +123 -0
  91. package/dist/components/PageHeader.d.ts +7 -1
  92. package/dist/components/PageHeader.js +2 -2
  93. package/dist/components/Pagination.js +6 -5
  94. package/dist/components/PasswordInput.d.ts +34 -0
  95. package/dist/components/PasswordInput.js +101 -0
  96. package/dist/components/Peek.js +3 -3
  97. package/dist/components/Popover.js +2 -0
  98. package/dist/components/PrintLayout.d.ts +63 -0
  99. package/dist/components/PrintLayout.js +114 -0
  100. package/dist/components/QrCode.d.ts +47 -0
  101. package/dist/components/QrCode.js +55 -0
  102. package/dist/components/QrScanner.d.ts +95 -0
  103. package/dist/components/QrScanner.js +266 -0
  104. package/dist/components/RelationshipGraph.d.ts +32 -1
  105. package/dist/components/RelationshipGraph.js +18 -5
  106. package/dist/components/RelationshipGraphLayered.d.ts +1 -1
  107. package/dist/components/RelationshipGraphLayered.js +190 -115
  108. package/dist/components/RelationshipGraphList.js +33 -6
  109. package/dist/components/RuleBuilder.js +39 -7
  110. package/dist/components/SaveStatus.d.ts +7 -1
  111. package/dist/components/SaveStatus.js +13 -4
  112. package/dist/components/SchedulingAgenda.d.ts +3 -1
  113. package/dist/components/SchedulingCalendar.d.ts +3 -1
  114. package/dist/components/SchedulingCalendar.js +43 -4
  115. package/dist/components/SchedulingResourceDay.d.ts +57 -0
  116. package/dist/components/SchedulingResourceDay.js +287 -0
  117. package/dist/components/SchedulingTimeGrid.d.ts +3 -1
  118. package/dist/components/SchedulingTimeline.d.ts +3 -1
  119. package/dist/components/SearchBar.d.ts +1 -0
  120. package/dist/components/SearchSuggest.d.ts +23 -3
  121. package/dist/components/SearchSuggest.js +48 -17
  122. package/dist/components/Segmented.d.ts +39 -4
  123. package/dist/components/Segmented.js +31 -3
  124. package/dist/components/Select.d.ts +3 -2
  125. package/dist/components/Select.js +1 -1
  126. package/dist/components/ShortcutHint.d.ts +11 -10
  127. package/dist/components/ShortcutHint.js +44 -38
  128. package/dist/components/Sidebar.d.ts +36 -4
  129. package/dist/components/Sidebar.js +37 -12
  130. package/dist/components/SortableList.d.ts +45 -0
  131. package/dist/components/SortableList.js +134 -0
  132. package/dist/components/Spinner.d.ts +7 -1
  133. package/dist/components/Spinner.js +7 -1
  134. package/dist/components/Stat.d.ts +28 -3
  135. package/dist/components/Stat.js +13 -3
  136. package/dist/components/States.d.ts +7 -1
  137. package/dist/components/States.js +7 -1
  138. package/dist/components/StatusPill.d.ts +14 -3
  139. package/dist/components/StatusPill.js +11 -3
  140. package/dist/components/Steps.js +2 -1
  141. package/dist/components/Table.d.ts +16 -2
  142. package/dist/components/Table.js +8 -4
  143. package/dist/components/TableControls.js +18 -58
  144. package/dist/components/TableOverflowProbe.d.ts +12 -0
  145. package/dist/components/TableOverflowProbe.js +27 -0
  146. package/dist/components/Tabs.d.ts +2 -1
  147. package/dist/components/Tabs.js +1 -0
  148. package/dist/components/TagInput.d.ts +67 -0
  149. package/dist/components/TagInput.js +342 -0
  150. package/dist/components/Textarea.d.ts +5 -0
  151. package/dist/components/Textarea.js +2 -2
  152. package/dist/components/TimePicker.d.ts +80 -0
  153. package/dist/components/TimePicker.js +347 -0
  154. package/dist/components/Toast.js +3 -2
  155. package/dist/components/Tooltip.d.ts +8 -4
  156. package/dist/components/Tooltip.js +24 -21
  157. package/dist/components/Tree.d.ts +8 -0
  158. package/dist/components/Tree.js +11 -5
  159. package/dist/display-preferences-model.d.ts +53 -0
  160. package/dist/display-preferences-model.js +64 -0
  161. package/dist/emoji.cjs +28 -35
  162. package/dist/filter-model.d.ts +59 -3
  163. package/dist/filter-model.js +67 -2
  164. package/dist/hooks/useChangeHighlight.d.ts +33 -0
  165. package/dist/hooks/useChangeHighlight.js +44 -0
  166. package/dist/hooks/useDelayedPending.d.ts +22 -0
  167. package/dist/hooks/useDelayedPending.js +35 -0
  168. package/dist/hooks/useDialog.d.ts +5 -0
  169. package/dist/hooks/useDialog.js +3 -2
  170. package/dist/hooks/useOptimisticValue.d.ts +51 -0
  171. package/dist/hooks/useOptimisticValue.js +61 -0
  172. package/dist/hooks/useReducedMotion.d.ts +4 -1
  173. package/dist/hooks/useReducedMotion.js +7 -1
  174. package/dist/hooks/useResolvedFilterLabels.d.ts +15 -0
  175. package/dist/hooks/useResolvedFilterLabels.js +34 -0
  176. package/dist/hooks/useVirtualRows.d.ts +21 -2
  177. package/dist/hooks/useVirtualRows.js +30 -3
  178. package/dist/icons/Icon.d.ts +1 -1
  179. package/dist/index.cjs +18977 -13378
  180. package/dist/index.d.cts +3065 -664
  181. package/dist/index.d.ts +46 -16
  182. package/dist/index.js +149 -7
  183. package/dist/labels-context.d.ts +93 -3
  184. package/dist/motion-timing.d.ts +8 -0
  185. package/dist/motion-timing.js +8 -0
  186. package/dist/overlay-stack.d.ts +6 -0
  187. package/dist/overlay-stack.js +13 -0
  188. package/dist/qr-model.d.ts +65 -0
  189. package/dist/qr-model.js +323 -0
  190. package/dist/relationship-graph-model.d.ts +78 -3
  191. package/dist/relationship-graph-model.js +112 -5
  192. package/dist/reorder.d.ts +30 -0
  193. package/dist/reorder.js +74 -0
  194. package/dist/rich-text.cjs +4 -2
  195. package/dist/scheduling-resource-model.d.ts +76 -0
  196. package/dist/scheduling-resource-model.js +74 -0
  197. package/dist/search-suggest-model.js +3 -1
  198. package/dist/shell-context.d.ts +11 -0
  199. package/dist/shell-context.js +7 -0
  200. package/dist/time-field-model.d.ts +46 -0
  201. package/dist/time-field-model.js +152 -0
  202. package/dist/toast-store.d.ts +17 -1
  203. package/dist/toast-store.js +23 -7
  204. package/package.json +2 -1
@@ -0,0 +1,123 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { forwardRef, Fragment, useEffect, useImperativeHandle, useRef, useState } from "react";
4
+ import { cx } from "../cx.js";
5
+ const allowed = (text, mode) => {
6
+ const plain = text.normalize("NFKC");
7
+ return mode === "numeric" ? plain.replace(/\D+/g, "") : plain.replace(/[^0-9a-z]+/gi, "").toUpperCase();
8
+ };
9
+ const clean = (text, mode, length) => allowed(text, mode).slice(0, length);
10
+ const OtpInput = forwardRef(function OtpInput2({
11
+ length: lengthProp = 6,
12
+ value: valueProp,
13
+ defaultValue = "",
14
+ onValueChange,
15
+ onComplete,
16
+ mode = "numeric",
17
+ groupSize,
18
+ invalid,
19
+ "aria-invalid": ariaInvalid,
20
+ className,
21
+ style,
22
+ autoComplete = "one-time-code",
23
+ onFocus,
24
+ onBlur,
25
+ onSelect,
26
+ disabled,
27
+ ...props
28
+ }, forwardedRef) {
29
+ const length = Math.max(1, Math.floor(lengthProp));
30
+ const [internal, setInternal] = useState(() => clean(defaultValue, mode, length));
31
+ const value = valueProp !== void 0 ? clean(valueProp, mode, length) : internal;
32
+ const [focused, setFocused] = useState(false);
33
+ const inputRef = useRef(null);
34
+ useImperativeHandle(forwardedRef, () => inputRef.current);
35
+ const completed = useRef(value.length === length ? value : null);
36
+ const update = (raw) => {
37
+ const next = clean(raw, mode, length);
38
+ if (valueProp === void 0) setInternal(next);
39
+ if (next !== value) onValueChange?.(next);
40
+ };
41
+ useEffect(() => {
42
+ if (value.length === length && completed.current !== value) {
43
+ completed.current = value;
44
+ onComplete?.(value);
45
+ } else if (value.length < length) {
46
+ completed.current = null;
47
+ }
48
+ }, [value, length]);
49
+ const toEnd = () => {
50
+ const input = inputRef.current;
51
+ if (!input) return;
52
+ const all = input.value.length > 0 && input.selectionStart === 0 && input.selectionEnd === input.value.length;
53
+ if (!all && (input.selectionStart !== input.value.length || input.selectionEnd !== input.value.length)) {
54
+ try {
55
+ input.setSelectionRange(input.value.length, input.value.length);
56
+ } catch {
57
+ }
58
+ }
59
+ };
60
+ const isInvalid = !!invalid || ariaInvalid === true || ariaInvalid === "true";
61
+ const active = focused ? Math.min(value.length, length - 1) : -1;
62
+ const group = groupSize && groupSize > 0 && groupSize < length ? Math.floor(groupSize) : 0;
63
+ return /* @__PURE__ */ jsxs(
64
+ "div",
65
+ {
66
+ className: cx("uix-otp", className),
67
+ style: { "--uix-otp-cells": length, "--uix-otp-seps": group ? Math.ceil(length / group) - 1 : 0, ...style },
68
+ children: [
69
+ /* @__PURE__ */ jsx(
70
+ "input",
71
+ {
72
+ ...props,
73
+ ref: inputRef,
74
+ className: "uix-otp__input",
75
+ type: "text",
76
+ inputMode: mode === "numeric" ? "numeric" : "text",
77
+ autoComplete,
78
+ autoCapitalize: mode === "alphanumeric" ? "characters" : "off",
79
+ autoCorrect: "off",
80
+ spellCheck: false,
81
+ pattern: mode === "numeric" ? `[0-9]{${length}}` : `[0-9A-Za-z]{${length}}`,
82
+ dir: "ltr",
83
+ value,
84
+ disabled,
85
+ "aria-invalid": isInvalid || void 0,
86
+ onChange: (event) => update(event.target.value),
87
+ onPaste: (event) => {
88
+ const usable = allowed(event.clipboardData?.getData("text") ?? "", mode);
89
+ event.preventDefault();
90
+ if (!usable) return;
91
+ const input = event.currentTarget;
92
+ const start = input.selectionStart ?? value.length;
93
+ const end = input.selectionEnd ?? value.length;
94
+ const whole = start === 0 && end === value.length;
95
+ update(whole ? usable : `${value.slice(0, start)}${usable}${value.slice(end)}`);
96
+ },
97
+ onFocus: (event) => {
98
+ setFocused(true);
99
+ toEnd();
100
+ onFocus?.(event);
101
+ },
102
+ onBlur: (event) => {
103
+ setFocused(false);
104
+ onBlur?.(event);
105
+ },
106
+ onSelect: (event) => {
107
+ toEnd();
108
+ onSelect?.(event);
109
+ }
110
+ }
111
+ ),
112
+ Array.from({ length }, (_, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
113
+ group > 0 && index > 0 && index % group === 0 && /* @__PURE__ */ jsx("span", { className: "uix-otp__sep", "aria-hidden": "true" }),
114
+ /* @__PURE__ */ jsx("span", { className: "uix-otp__cell", "aria-hidden": "true", "data-active": index === active || void 0, children: value[index] ?? "" })
115
+ ] }, index))
116
+ ]
117
+ }
118
+ );
119
+ });
120
+ OtpInput.displayName = "OtpInput";
121
+ export {
122
+ OtpInput
123
+ };
@@ -17,11 +17,17 @@ interface PageHeaderProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
17
17
  helpLabel?: string;
18
18
  /** Right-aligned action area (buttons, menus). */
19
19
  actions?: ReactNode;
20
+ /**
21
+ * `display` is the staff type preset (HAR-1815; TENSOR, MOTUS ADR-0047): a 40 px heading-font
22
+ * title, a bold hushed eyebrow, a body-size hushed subtitle up to 42rem, and the actions
23
+ * aligned to the bottom of the titles. `default` is the 24 px header.
24
+ */
25
+ size?: 'default' | 'display';
20
26
  }
21
27
  /**
22
28
  * Page header — eyebrow / title (+ optional `help` ?) / subtitle + actions row, over `.uix-page-header`.
23
29
  * The hairline + breathing room below come from the component CSS.
24
30
  */
25
- declare function PageHeader({ eyebrow, title, subtitle, help, helpLabel, actions, as: TitleTag, className, ...props }: PageHeaderProps): react.JSX.Element;
31
+ declare function PageHeader({ eyebrow, title, subtitle, help, helpLabel, actions, as: TitleTag, size, className, ...props }: PageHeaderProps): react.JSX.Element;
26
32
 
27
33
  export { PageHeader, type PageHeaderProps };
@@ -2,9 +2,9 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { cx } from "../cx.js";
3
3
  import { InfoTip } from "./InfoTip.js";
4
4
  import { hasHelp, helpLabelFor } from "../info-tip-model.js";
5
- function PageHeader({ eyebrow, title, subtitle, help, helpLabel, actions, as: TitleTag = "h1", className, ...props }) {
5
+ function PageHeader({ eyebrow, title, subtitle, help, helpLabel, actions, as: TitleTag = "h1", size = "default", className, ...props }) {
6
6
  const heading = /* @__PURE__ */ jsx(TitleTag, { className: "uix-page-header__title", children: title });
7
- return /* @__PURE__ */ jsxs("header", { className: cx("uix-page-header", className), ...props, children: [
7
+ return /* @__PURE__ */ jsxs("header", { className: cx("uix-page-header", size === "display" && "uix-page-header--display", className), ...props, children: [
8
8
  /* @__PURE__ */ jsxs("div", { className: "uix-page-header__titles", children: [
9
9
  eyebrow != null && /* @__PURE__ */ jsx("div", { className: "uix-page-header__eyebrow", children: eyebrow }),
10
10
  hasHelp(help) ? /* @__PURE__ */ jsxs("div", { className: "uix-page-header__title-row", children: [
@@ -2,6 +2,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Fragment as Fragment2 } from "react";
3
3
  import { cx } from "../cx.js";
4
4
  import { renderUixLink } from "../link.js";
5
+ import { ChevronLeftIcon, ChevronRightIcon, ChevronsLeftIcon } from "../icons/components.js";
5
6
  function getPageNumbers(page, total) {
6
7
  if (total <= 7) return Array.from({ length: total }, (_, i) => i + 1);
7
8
  const pages = [1];
@@ -59,19 +60,19 @@ function Pagination({
59
60
  if (mode === "cursor") {
60
61
  const linked = firstHref != null || previousHref != null || nextHref != null;
61
62
  controls = /* @__PURE__ */ jsxs(Fragment, { children: [
62
- (onFirst || firstHref != null) && render({ key: "first", content: "\xAB", label: labels.first, disabled: !hasPrevious, href: linked ? firstHref ?? "" : void 0, onClick: onFirst }),
63
- render({ key: "prev", content: "\u2039", label: labels.previous, disabled: !hasPrevious, href: linked ? previousHref ?? "" : void 0, onClick: onPrevious }),
63
+ (onFirst || firstHref != null) && render({ key: "first", content: /* @__PURE__ */ jsx(ChevronsLeftIcon, {}), label: labels.first, disabled: !hasPrevious, href: linked ? firstHref ?? "" : void 0, onClick: onFirst }),
64
+ render({ key: "prev", content: /* @__PURE__ */ jsx(ChevronLeftIcon, {}), label: labels.previous, disabled: !hasPrevious, href: linked ? previousHref ?? "" : void 0, onClick: onPrevious }),
64
65
  summary != null && /* @__PURE__ */ jsx("span", { className: "uix-pagination__summary", children: summary }),
65
- render({ key: "next", content: "\u203A", label: labels.next, disabled: !hasNext, href: linked ? nextHref ?? "" : void 0, onClick: onNext })
66
+ render({ key: "next", content: /* @__PURE__ */ jsx(ChevronRightIcon, {}), label: labels.next, disabled: !hasNext, href: linked ? nextHref ?? "" : void 0, onClick: onNext })
66
67
  ] });
67
68
  } else {
68
69
  const go = (target) => hrefFor ? { href: hrefFor(target) } : { onClick: () => onChange?.(target) };
69
70
  controls = /* @__PURE__ */ jsxs(Fragment, { children: [
70
- render({ key: "prev", content: "\u2039", label: labels.previous, disabled: page <= 1, ...go(page - 1) }),
71
+ render({ key: "prev", content: /* @__PURE__ */ jsx(ChevronLeftIcon, {}), label: labels.previous, disabled: page <= 1, ...go(page - 1) }),
71
72
  getPageNumbers(page, pageCount).map(
72
73
  (p, i) => p === "ellipsis" ? /* @__PURE__ */ jsx("span", { className: "uix-pagination__ellipsis", children: "\u2026" }, `e${i}`) : render({ key: `p${p}`, content: p, current: p === page, ...go(p) })
73
74
  ),
74
- render({ key: "next", content: "\u203A", label: labels.next, disabled: page >= pageCount, ...go(page + 1) })
75
+ render({ key: "next", content: /* @__PURE__ */ jsx(ChevronRightIcon, {}), label: labels.next, disabled: page >= pageCount, ...go(page + 1) })
75
76
  ] });
76
77
  }
77
78
  return /* @__PURE__ */ jsx("nav", { "aria-label": labels.region, className: cx("uix-pagination", className), ...props, children: controls });
@@ -0,0 +1,34 @@
1
+ import * as react from 'react';
2
+ import { InputProps } from './Input.js';
3
+
4
+ /** The words `PasswordInput` renders. */
5
+ interface PasswordInputLabels {
6
+ /**
7
+ * Name of the reveal toggle. It stays the same while the password shows: the toggle's pressed
8
+ * state (`aria-pressed`) says whether it is on.
9
+ */
10
+ show: string;
11
+ }
12
+ declare const DEFAULT_PASSWORD_INPUT_LABELS: PasswordInputLabels;
13
+ interface PasswordInputProps extends Omit<InputProps, 'type'> {
14
+ /** Controlled: whether the password shows as text. */
15
+ revealed?: boolean;
16
+ /** Uncontrolled: shown as text at first. Default `false`. */
17
+ defaultRevealed?: boolean;
18
+ onRevealedChange?: (revealed: boolean) => void;
19
+ /** Each word defaults to `UixLabelsProvider` `passwordInput`, then to English. */
20
+ labels?: Partial<PasswordInputLabels>;
21
+ /** Class of the wrapping `InputGroup` (`className` goes on the input). */
22
+ groupClassName?: string;
23
+ }
24
+ /**
25
+ * A password field with a reveal toggle (HAR-1376): an `Input type="password"` and, inside its end,
26
+ * a toggle button (`aria-pressed`) that shows the password as text and hides it again. A pointer
27
+ * press leaves focus in the field; the keyboard reaches the toggle with Tab. The password is
28
+ * hidden again when its form submits, so a password manager sees a password field. `autoComplete`
29
+ * passes through (`current-password`, `new-password`); inside `Field` the label, hint and error
30
+ * land on the input. `ref` is the input.
31
+ */
32
+ declare const PasswordInput: react.ForwardRefExoticComponent<PasswordInputProps & react.RefAttributes<HTMLInputElement>>;
33
+
34
+ export { DEFAULT_PASSWORD_INPUT_LABELS, PasswordInput, type PasswordInputLabels, type PasswordInputProps };
@@ -0,0 +1,101 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { forwardRef, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from "react";
4
+ import { EyeIcon, EyeOffIcon } from "../icons/components.js";
5
+ import { useUixLabels } from "../labels-context.js";
6
+ import { Input, InputGroup } from "./Input.js";
7
+ const useIsomorphicLayoutEffect = typeof document !== "undefined" ? useLayoutEffect : useEffect;
8
+ const DEFAULT_PASSWORD_INPUT_LABELS = { show: "Show password" };
9
+ const PasswordInput = forwardRef(function PasswordInput2({
10
+ revealed: revealedProp,
11
+ defaultRevealed = false,
12
+ onRevealedChange,
13
+ labels: labelOverrides,
14
+ groupClassName,
15
+ disabled,
16
+ size,
17
+ ...props
18
+ }, forwardedRef) {
19
+ const labels = { ...DEFAULT_PASSWORD_INPUT_LABELS, ...useUixLabels().passwordInput, ...labelOverrides };
20
+ const [internal, setInternal] = useState(defaultRevealed);
21
+ const revealed = revealedProp ?? internal;
22
+ const inputRef = useRef(null);
23
+ useImperativeHandle(forwardedRef, () => inputRef.current);
24
+ const revealedRef = useRef(revealed);
25
+ revealedRef.current = revealed;
26
+ const setRevealed = (next) => {
27
+ if (revealedProp === void 0) setInternal(next);
28
+ onRevealedChange?.(next);
29
+ };
30
+ const setRef = useRef(setRevealed);
31
+ setRef.current = setRevealed;
32
+ const selection = useRef(null);
33
+ const keepSelection = () => {
34
+ const input = inputRef.current;
35
+ if (!input || input.ownerDocument.activeElement !== input) {
36
+ selection.current = null;
37
+ return;
38
+ }
39
+ selection.current = { start: input.selectionStart ?? input.value.length, end: input.selectionEnd ?? input.value.length, direction: input.selectionDirection ?? "none" };
40
+ };
41
+ useIsomorphicLayoutEffect(() => {
42
+ const input = inputRef.current;
43
+ const kept = selection.current;
44
+ selection.current = null;
45
+ if (!input || !kept || input.ownerDocument.activeElement !== input) return;
46
+ void input.offsetWidth;
47
+ try {
48
+ input.setSelectionRange(kept.start, kept.end, kept.direction);
49
+ } catch {
50
+ }
51
+ }, [revealed]);
52
+ useEffect(() => {
53
+ const form = inputRef.current?.form;
54
+ if (!form) return void 0;
55
+ const onSubmit = () => {
56
+ if (revealedRef.current) setRef.current(false);
57
+ };
58
+ form.addEventListener("submit", onSubmit, true);
59
+ return () => form.removeEventListener("submit", onSubmit, true);
60
+ }, []);
61
+ return /* @__PURE__ */ jsx(
62
+ InputGroup,
63
+ {
64
+ className: groupClassName,
65
+ trailingAction: /* @__PURE__ */ jsx(
66
+ "button",
67
+ {
68
+ type: "button",
69
+ className: "uix-input-group__action",
70
+ "aria-label": labels.show,
71
+ "aria-pressed": revealed,
72
+ "aria-controls": props.id,
73
+ disabled,
74
+ onMouseDown: (event) => event.preventDefault(),
75
+ onClick: () => {
76
+ keepSelection();
77
+ setRevealed(!revealed);
78
+ },
79
+ children: revealed ? /* @__PURE__ */ jsx(EyeOffIcon, { size: "sm" }) : /* @__PURE__ */ jsx(EyeIcon, { size: "sm" })
80
+ }
81
+ ),
82
+ children: /* @__PURE__ */ jsx(
83
+ Input,
84
+ {
85
+ ...props,
86
+ ref: inputRef,
87
+ size,
88
+ disabled,
89
+ type: revealed ? "text" : "password",
90
+ spellCheck: false,
91
+ autoCapitalize: "none"
92
+ }
93
+ )
94
+ }
95
+ );
96
+ });
97
+ PasswordInput.displayName = "PasswordInput";
98
+ export {
99
+ DEFAULT_PASSWORD_INPUT_LABELS,
100
+ PasswordInput
101
+ };
@@ -19,12 +19,12 @@ function Peek({ open, onClose, title, children, footer, onNavPrev, onNavNext, hi
19
19
  return /* @__PURE__ */ jsxs("dialog", { ref, className: cx("uix-peek", className), "aria-labelledby": title ? titleId : void 0, ...rest, onClick: backdropDismiss(onClose, onClick), children: [
20
20
  /* @__PURE__ */ jsxs("div", { className: "uix-peek__header", children: [
21
21
  hasNav && /* @__PURE__ */ jsxs("div", { className: "uix-peek__nav", children: [
22
- /* @__PURE__ */ jsx("button", { className: "uix-peek__navbtn", onClick: () => onNavPrev?.(), "aria-disabled": onNavPrev ? void 0 : true, "aria-label": previousLabel, children: /* @__PURE__ */ jsx(ChevronUp, {}) }),
23
- /* @__PURE__ */ jsx("button", { className: "uix-peek__navbtn", onClick: () => onNavNext?.(), "aria-disabled": onNavNext ? void 0 : true, "aria-label": nextLabel, children: /* @__PURE__ */ jsx(ChevronDown, {}) })
22
+ /* @__PURE__ */ jsx("button", { type: "button", className: "uix-peek__navbtn", onClick: () => onNavPrev?.(), "aria-disabled": onNavPrev ? void 0 : true, "aria-label": previousLabel, children: /* @__PURE__ */ jsx(ChevronUp, {}) }),
23
+ /* @__PURE__ */ jsx("button", { type: "button", className: "uix-peek__navbtn", onClick: () => onNavNext?.(), "aria-disabled": onNavNext ? void 0 : true, "aria-label": nextLabel, children: /* @__PURE__ */ jsx(ChevronDown, {}) })
24
24
  ] }),
25
25
  title && /* @__PURE__ */ jsx("h2", { className: "uix-peek__title", id: titleId, children: title }),
26
26
  hint && /* @__PURE__ */ jsx("span", { className: "uix-peek__hint", children: hint }),
27
- onClose && /* @__PURE__ */ jsx("button", { className: "uix-peek__close", onClick: onClose, "aria-label": closeLabel, children: /* @__PURE__ */ jsx(CloseIcon, {}) })
27
+ onClose && /* @__PURE__ */ jsx("button", { type: "button", className: "uix-peek__close", onClick: onClose, "aria-label": closeLabel, children: /* @__PURE__ */ jsx(CloseIcon, {}) })
28
28
  ] }),
29
29
  children != null && /* @__PURE__ */ jsx("div", { className: "uix-peek__body", children }),
30
30
  footer != null && /* @__PURE__ */ jsx("div", { className: "uix-peek__footer", children: footer })
@@ -134,6 +134,8 @@ function Popover({
134
134
  };
135
135
  const onKeyDown = (event) => {
136
136
  if (event.key !== "Escape" || !isPopoverOpen(el)) return;
137
+ event.preventDefault();
138
+ event.stopPropagation();
137
139
  window.clearTimeout(timer);
138
140
  const hadFocus = el.contains(el.ownerDocument.activeElement);
139
141
  try {
@@ -0,0 +1,63 @@
1
+ import * as react from 'react';
2
+ import { HTMLAttributes, ReactNode } from 'react';
3
+
4
+ /** The words of `PrintSignature` (HAR-986). */
5
+ interface PrintLayoutLabels {
6
+ /** The caption under the signature line. */
7
+ signature: string;
8
+ /** The caption of the stamp box. */
9
+ stamp: string;
10
+ }
11
+ declare const DEFAULT_PRINT_LAYOUT_LABELS: PrintLayoutLabels;
12
+ type PrintPageSize = 'A4' | 'A5';
13
+ interface PrintLayoutProps extends HTMLAttributes<HTMLDivElement> {
14
+ /** The paper. Default `A4` (210 × 297 mm); `A5` is 148 × 210 mm (a poster, a slip). */
15
+ size?: PrintPageSize;
16
+ /** Default `portrait`. */
17
+ orientation?: 'portrait' | 'landscape';
18
+ /** Repeats at the top of every printed page: the practice or store identity. */
19
+ header?: ReactNode;
20
+ /** Repeats at the foot of every printed page, before the page number. */
21
+ footer?: ReactNode;
22
+ /** "page / pages" in the bottom-right page margin of every printed page. Default `true`; never on a `singlePage` layout. */
23
+ pageNumbers?: boolean;
24
+ /**
25
+ * One page and no more (a poster, a one-page readout): the header and footer are not
26
+ * repeated, the layout is kept in one piece, and the screen preview is exactly one page tall.
27
+ * When the content does not fit, the preview is outlined and `onOverflowChange(true)` is called,
28
+ * so the product can shorten it before anyone prints.
29
+ */
30
+ singlePage?: boolean;
31
+ /** Called with `true` when a `singlePage` layout's content is taller than its page, and `false` once it fits again. */
32
+ onOverflowChange?: (overflowing: boolean) => void;
33
+ /**
34
+ * When printing, show only print layouts: everything else on the page (the app shell, the
35
+ * toolbar with the Print button, toasts, dialogs) is hidden. Default `true`.
36
+ */
37
+ isolate?: boolean;
38
+ }
39
+ /**
40
+ * A print document frame (HAR-986, HAR-1252; MEDx S20 "Nalaz i mišljenje" and the day list,
41
+ * SHOPx PRE-01 A5 poster and SHOP-03 one-page readout): an A4 or A5 page with the paper's margins,
42
+ * a header and a footer that repeat on every printed page, page numbers in the page margin, and
43
+ * black-on-white tokens for everything inside, on screen (as a paper preview) and on paper. The
44
+ * consumer supplies the sections; the browser's own print (`window.print()`) makes the pages.
45
+ */
46
+ declare function PrintLayout({ size, orientation, header, footer, pageNumbers, singlePage, onOverflowChange, isolate, className, children, style, ...props }: PrintLayoutProps): react.JSX.Element;
47
+ interface PrintSignatureProps extends HTMLAttributes<HTMLDivElement> {
48
+ /** The caption under the line. Default `labels.signature`. */
49
+ label?: ReactNode;
50
+ /** The signer's printed name and title under the caption, e.g. "dr. Amra Hadžić, spec. pedijatrije". */
51
+ name?: ReactNode;
52
+ /** Place and date at the start of the block, e.g. "Sarajevo, 22. 10. 2026.". */
53
+ placeAndDate?: ReactNode;
54
+ /** A box for the stamp beside the signature. */
55
+ stamp?: boolean;
56
+ labels?: Partial<PrintLayoutLabels>;
57
+ }
58
+ /** A signature line (and an optional stamp box) that is never split across two pages. */
59
+ declare function PrintSignature({ label, name, placeAndDate, stamp, labels: labelsProp, className, ...props }: PrintSignatureProps): react.JSX.Element;
60
+ /** Starts a new printed page here. On screen it is a dashed line, so the preview shows where the page ends. */
61
+ declare function PrintPageBreak({ className, ...props }: HTMLAttributes<HTMLDivElement>): react.JSX.Element;
62
+
63
+ export { DEFAULT_PRINT_LAYOUT_LABELS, PrintLayout, type PrintLayoutLabels, type PrintLayoutProps, PrintPageBreak, type PrintPageSize, PrintSignature, type PrintSignatureProps };
@@ -0,0 +1,114 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useLayoutEffect, useRef, useState } from "react";
4
+ import { cx } from "../cx.js";
5
+ import { useUixLabels } from "../labels-context.js";
6
+ const DEFAULT_PRINT_LAYOUT_LABELS = { signature: "Signature", stamp: "Stamp" };
7
+ const useIsomorphicLayoutEffect = typeof document !== "undefined" ? useLayoutEffect : useEffect;
8
+ const PAPER_MM = { A4: [210, 297], A5: [148, 210] };
9
+ const PX_PER_MM = 96 / 25.4;
10
+ function PrintLayout({
11
+ size = "A4",
12
+ orientation = "portrait",
13
+ header,
14
+ footer,
15
+ pageNumbers = true,
16
+ singlePage = false,
17
+ onOverflowChange,
18
+ isolate = true,
19
+ className,
20
+ children,
21
+ style,
22
+ ...props
23
+ }) {
24
+ const ref = useRef(null);
25
+ const fitRef = useRef(null);
26
+ const report = useRef(onOverflowChange);
27
+ report.current = onOverflowChange;
28
+ const [scale, setScale] = useState(1);
29
+ const paperMm = PAPER_MM[size][orientation === "landscape" ? 1 : 0];
30
+ const paperPx = paperMm * PX_PER_MM;
31
+ useIsomorphicLayoutEffect(() => {
32
+ const box = fitRef.current;
33
+ if (!box) return void 0;
34
+ const fit = () => {
35
+ const room = box.getBoundingClientRect().width;
36
+ if (room > 0) setScale(room >= paperPx - 0.5 ? 1 : room / paperPx);
37
+ };
38
+ fit();
39
+ if (typeof ResizeObserver === "undefined") return void 0;
40
+ const observer = new ResizeObserver(fit);
41
+ observer.observe(box);
42
+ return () => observer.disconnect();
43
+ }, [paperPx]);
44
+ const hasHeader = header != null;
45
+ const hasFooter = footer != null;
46
+ useEffect(() => {
47
+ const root = ref.current;
48
+ if (!singlePage || !root || typeof ResizeObserver === "undefined") return void 0;
49
+ const content = root.querySelector(":scope > .uix-print-layout__page");
50
+ if (!content) return void 0;
51
+ let last = false;
52
+ let frame = 0;
53
+ const measure = () => {
54
+ frame = 0;
55
+ const over = content.scrollHeight > content.clientHeight + 1;
56
+ if (over === last) return;
57
+ last = over;
58
+ root.toggleAttribute("data-overflowing", over);
59
+ report.current?.(over);
60
+ };
61
+ const observer = new ResizeObserver(() => {
62
+ if (!frame) frame = requestAnimationFrame(measure);
63
+ });
64
+ observer.observe(content);
65
+ for (const cell of Array.from(content.querySelectorAll(":scope > * > tr > td"))) observer.observe(cell);
66
+ measure();
67
+ return () => {
68
+ observer.disconnect();
69
+ if (frame) cancelAnimationFrame(frame);
70
+ };
71
+ }, [singlePage, hasHeader, hasFooter]);
72
+ const page = `uix-print-${size.toLowerCase()}${orientation === "landscape" ? "-landscape" : ""}${pageNumbers && !singlePage ? "" : "-plain"}`;
73
+ return /* @__PURE__ */ jsx("div", { ref: fitRef, className: "uix-print-preview", style: { inlineSize: `${paperMm}mm` }, children: /* @__PURE__ */ jsx(
74
+ "div",
75
+ {
76
+ ref,
77
+ className: cx("uix-print-layout", className),
78
+ "data-size": size,
79
+ "data-orientation": orientation,
80
+ "data-page": page,
81
+ "data-single-page": singlePage ? "" : void 0,
82
+ "data-isolate": isolate ? "" : void 0,
83
+ style: scale < 1 ? { "--uix-print-preview-scale": Number(scale.toFixed(4)), ...style } : style,
84
+ ...props,
85
+ children: /* @__PURE__ */ jsxs("table", { className: "uix-print-layout__page", role: "presentation", children: [
86
+ header != null && /* @__PURE__ */ jsx("thead", { className: "uix-print-layout__header", children: /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("div", { className: "uix-print-layout__bar", children: header }) }) }) }),
87
+ /* @__PURE__ */ jsx("tbody", { className: "uix-print-layout__main", children: /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { className: "uix-print-layout__body", children }) }) }),
88
+ footer != null && /* @__PURE__ */ jsx("tfoot", { className: "uix-print-layout__footer", children: /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("div", { className: "uix-print-layout__bar", children: footer }) }) }) })
89
+ ] })
90
+ }
91
+ ) });
92
+ }
93
+ function PrintSignature({ label, name, placeAndDate, stamp = false, labels: labelsProp, className, ...props }) {
94
+ const uixLabels = useUixLabels();
95
+ const labels = { ...DEFAULT_PRINT_LAYOUT_LABELS, ...uixLabels.printLayout, ...labelsProp };
96
+ return /* @__PURE__ */ jsxs("div", { className: cx("uix-print-signature", className), ...props, children: [
97
+ placeAndDate != null && /* @__PURE__ */ jsx("div", { className: "uix-print-signature__place", children: placeAndDate }),
98
+ /* @__PURE__ */ jsxs("div", { className: "uix-print-signature__field", children: [
99
+ /* @__PURE__ */ jsx("div", { className: "uix-print-signature__line", "aria-hidden": "true" }),
100
+ /* @__PURE__ */ jsx("div", { className: "uix-print-signature__caption", children: label ?? labels.signature }),
101
+ name != null && /* @__PURE__ */ jsx("div", { className: "uix-print-signature__name", children: name })
102
+ ] }),
103
+ stamp && /* @__PURE__ */ jsx("div", { className: "uix-print-signature__stamp", children: /* @__PURE__ */ jsx("span", { children: labels.stamp }) })
104
+ ] });
105
+ }
106
+ function PrintPageBreak({ className, ...props }) {
107
+ return /* @__PURE__ */ jsx("div", { className: cx("uix-print-break", className), role: "presentation", ...props });
108
+ }
109
+ export {
110
+ DEFAULT_PRINT_LAYOUT_LABELS,
111
+ PrintLayout,
112
+ PrintPageBreak,
113
+ PrintSignature
114
+ };
@@ -0,0 +1,47 @@
1
+ import * as react from 'react';
2
+ import { SVGAttributes } from 'react';
3
+ import { QrErrorCorrection } from '../qr-model.js';
4
+
5
+ /** The words of a `QrCode` (HAR-1251). */
6
+ interface QrCodeLabels {
7
+ /** Shown in place of the symbol when `value` does not fit in a QR code at the chosen level. */
8
+ tooLong: string;
9
+ }
10
+ /** The English words of `QrCode`, the base `UixLabelsProvider` `qrCode` and `labels` override. */
11
+ declare const DEFAULT_QR_CODE_LABELS: QrCodeLabels;
12
+ interface QrCodeProps extends Omit<SVGAttributes<SVGSVGElement>, 'children' | 'width' | 'height' | 'viewBox'> {
13
+ /** The text to encode, e.g. the campaign URL. Encoded as UTF-8 bytes. */
14
+ value: string;
15
+ /**
16
+ * The symbol's accessible name, e.g. "QR code: open the summer campaign". Say where it leads;
17
+ * the image itself tells a screen-reader user nothing.
18
+ */
19
+ label: string;
20
+ /**
21
+ * `L` 7 %, `M` 15 % (default), `Q` 25 %, `H` 30 % of the symbol may be lost and still read.
22
+ * Use `Q` or `H` for a poster that may be creased, scuffed or partly covered.
23
+ */
24
+ errorCorrection?: QrErrorCorrection;
25
+ /**
26
+ * The rendered width and height, quiet zone included: a number of CSS pixels (default 160) or
27
+ * any CSS length (`'32mm'` on paper). Keep at least 2 px per module on a screen and 0.4 mm per
28
+ * module on paper: a 30-character URL at `M` is version 3, 37 modules with the quiet zone, so
29
+ * at least 74 px or 15 mm.
30
+ */
31
+ size?: number | string;
32
+ /** The smallest version to use, so a set of posters gets symbols of one size. */
33
+ minVersion?: number;
34
+ /** Mark non-ASCII text as UTF-8 with an ECI designator (see `QrEncodeOptions.eci`). Default false. */
35
+ eci?: boolean;
36
+ /** The words. Default: `UixLabelsProvider` `qrCode`, then English. */
37
+ labels?: Partial<QrCodeLabels>;
38
+ }
39
+ /**
40
+ * A scannable, print-safe QR code (HAR-1251; SHOPx PRE-01 poster, voucher): `value` as an SVG
41
+ * with the standard four-module quiet zone, dark modules on light paper in every theme, in print
42
+ * and in forced colours (scanners read dark on light; an inverted symbol fails many of them).
43
+ * The encoder is the kit's own (`encodeQr`), so nothing is fetched and no library is added.
44
+ */
45
+ declare function QrCode({ value, label, errorCorrection, size, minVersion, eci, labels: labelsProp, className, style, ...props }: QrCodeProps): react.JSX.Element;
46
+
47
+ export { DEFAULT_QR_CODE_LABELS, QrCode, type QrCodeLabels, type QrCodeProps };
@@ -0,0 +1,55 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useMemo } from "react";
4
+ import { cx } from "../cx.js";
5
+ import { useUixLabels } from "../labels-context.js";
6
+ import { encodeQr, qrPath, QrCapacityError } from "../qr-model.js";
7
+ const DEFAULT_QR_CODE_LABELS = { tooLong: "Too long for a QR code" };
8
+ const QUIET_ZONE = 4;
9
+ function QrCode({ value, label, errorCorrection = "M", size = 160, minVersion, eci = false, labels: labelsProp, className, style, ...props }) {
10
+ const uixLabels = useUixLabels();
11
+ const labels = { ...DEFAULT_QR_CODE_LABELS, ...uixLabels.qrCode, ...labelsProp };
12
+ const matrix = useMemo(() => {
13
+ try {
14
+ return encodeQr(value, { errorCorrection, minVersion, eci });
15
+ } catch (error) {
16
+ if (error instanceof QrCapacityError) return void 0;
17
+ throw error;
18
+ }
19
+ }, [value, errorCorrection, minVersion, eci]);
20
+ const length = typeof size === "number" ? `${size}px` : size;
21
+ if (!matrix) {
22
+ return /* @__PURE__ */ jsxs("span", { ...props, className: cx("uix-qr-code", "uix-qr-code--error", className), style: { inlineSize: length, ...style }, children: [
23
+ /* @__PURE__ */ jsxs("span", { className: "uix-visually-hidden", children: [
24
+ label,
25
+ ": "
26
+ ] }),
27
+ labels.tooLong
28
+ ] });
29
+ }
30
+ const extent = matrix.size + QUIET_ZONE * 2;
31
+ return /* @__PURE__ */ jsxs(
32
+ "svg",
33
+ {
34
+ className: cx("uix-qr-code", className),
35
+ role: "img",
36
+ "aria-label": label,
37
+ viewBox: `0 0 ${extent} ${extent}`,
38
+ width: length,
39
+ height: length,
40
+ shapeRendering: "crispEdges",
41
+ "data-version": matrix.version,
42
+ "data-error-correction": matrix.errorCorrection,
43
+ style,
44
+ ...props,
45
+ children: [
46
+ /* @__PURE__ */ jsx("rect", { className: "uix-qr-code__paper", width: extent, height: extent }),
47
+ /* @__PURE__ */ jsx("path", { className: "uix-qr-code__ink", d: qrPath(matrix, QUIET_ZONE) })
48
+ ]
49
+ }
50
+ );
51
+ }
52
+ export {
53
+ DEFAULT_QR_CODE_LABELS,
54
+ QrCode
55
+ };