@orianatech/pire 1.2.0 → 1.3.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.
@@ -0,0 +1,60 @@
1
+ import * as React from 'react';
2
+ export interface NumPadKey {
3
+ /**
4
+ * What the key produces. A digit or a run of digits (`'7'`, `'00'`, `'000'`) is inserted into
5
+ * the buffer directly — that covers the whole base grid plus a money keypad's multi-zero keys
6
+ * for free. Anything else is a value NumPad cannot interpret on its own — an exact-balance
7
+ * button, say — so it is reported through {@link NumPadProps.onAction} instead of touched.
8
+ * `'backspace'` and `'clear'` are reserved: they always edit the buffer, never insert.
9
+ */
10
+ value: string;
11
+ /** Visible content. Falls back to `value` for a digit key; required for anything else — an
12
+ * action key has no default text that would make sense to show. */
13
+ label?: React.ReactNode;
14
+ /** Grid columns this key spans, in the 4-column layout. Defaults to 1. */
15
+ span?: 1 | 2;
16
+ }
17
+ export interface NumPadProps {
18
+ /** Names the key grid. Required: it is ~16 individually meaningless buttons ("7", "⌫"…), and
19
+ * nothing else on screen names the group of them. */
20
+ 'aria-label': string;
21
+ /** What is currently being edited — a selected line, the amount due. Announced through a live
22
+ * region on change, so a screen-reader user knows where their keystrokes are going before they
23
+ * press one. */
24
+ target?: React.ReactNode;
25
+ /** The buffer, controlled. NumPad renders no state of its own — the same principle
26
+ * `NumberField` follows by reading React Aria's state instead of mirroring it — so the grid
27
+ * and the physical keyboard can never disagree about what has been typed. */
28
+ value: string;
29
+ onChange: (value: string) => void;
30
+ /** Extra keys appended after the base grid (`7 8 9 C` / `4 5 6 ⌫` / `1 2 3 0`), in the same
31
+ * 4-column layout — a money keypad's `00`, `000` and a wide "exact balance" key. */
32
+ extraKeys?: NumPadKey[];
33
+ /**
34
+ * Fired when a key whose `value` is not purely digits is pressed (the base grid and any
35
+ * numeric `extraKeys` never call this — they go straight to `onChange`). The one place NumPad
36
+ * hands control back to the app: it cannot know what a key like `{ value: 'exact' }` should
37
+ * write into the buffer, only that it was pressed.
38
+ */
39
+ onAction?: (value: string) => void;
40
+ /** Disables every key at once — real `aria-disabled`, and a press does nothing, not just a
41
+ * colour change. Typical use: no line selected yet to type a quantity into. */
42
+ isDisabled?: boolean;
43
+ size?: 'md' | 'lg';
44
+ className?: string;
45
+ style?: React.CSSProperties;
46
+ }
47
+ /**
48
+ * An on-screen numeric keypad for a counter operated hands-on-keyboard: a POS quantity or an
49
+ * amount tendered, typed without looking down at the screen.
50
+ *
51
+ * Two defects the design it replaces had, and the reason both traps are closed here rather than
52
+ * left to each product: every press works from the physical keyboard as well as a click (see
53
+ * {@link useNumPadKeyboard}), and `isDisabled` is real — a native disabled `<button>`, not a
54
+ * class name a press still gets through.
55
+ *
56
+ * A screen with two of these mounted at once — a quantity keypad in a cart panel, an amount
57
+ * keypad in the payment overlay covering it — never has both answer the same keystroke either:
58
+ * see {@link useNumPadKeyboard} for how the backgrounded one recognises that on its own.
59
+ */
60
+ export declare function NumPad({ 'aria-label': ariaLabel, target, value, onChange, extraKeys, onAction, isDisabled, size, className, style, }: NumPadProps): React.JSX.Element;
@@ -0,0 +1,61 @@
1
+ import * as React from 'react';
2
+ export interface NumPadKey {
3
+ /**
4
+ * What the key produces. A digit or a run of digits (`'7'`, `'00'`, `'000'`) is inserted into
5
+ * the buffer directly — that covers the whole base grid plus a money keypad's multi-zero keys
6
+ * for free. Anything else is a value NumPad cannot interpret on its own — an exact-balance
7
+ * button, say — so it is reported through {@link NumPadProps.onAction} instead of touched.
8
+ * `'backspace'` and `'clear'` are reserved: they always edit the buffer, never insert.
9
+ */
10
+ value: string;
11
+ /** Visible content. Falls back to `value` for a digit key; required for anything else — an
12
+ * action key has no default text that would make sense to show. */
13
+ label?: React.ReactNode;
14
+ /** Grid columns this key spans, in the 4-column layout. Defaults to 1. */
15
+ span?: 1 | 2;
16
+ }
17
+ export interface NumPadProps {
18
+ /** Names the key grid. Required: it is ~16 individually meaningless buttons ("7", "⌫"…), and
19
+ * nothing else on screen names the group of them. */
20
+ 'aria-label': string;
21
+ /** What is currently being edited — a selected line, the amount due. Announced through a live
22
+ * region on change, so a screen-reader user knows where their keystrokes are going before they
23
+ * press one. */
24
+ target?: React.ReactNode;
25
+ /** The buffer, controlled. NumPad renders no state of its own — the same principle
26
+ * `NumberField` follows by reading React Aria's state instead of mirroring it — so the grid
27
+ * and the physical keyboard can never disagree about what has been typed. */
28
+ value: string;
29
+ onChange: (value: string) => void;
30
+ /** Extra keys appended after the base grid (`7 8 9 C` / `4 5 6 ⌫` / `1 2 3 0`), in the same
31
+ * 4-column layout — a money keypad's `00`, `000` and a wide "exact balance" key. */
32
+ extraKeys?: NumPadKey[];
33
+ /**
34
+ * Fired when a key whose `value` is not purely digits is pressed (the base grid and any
35
+ * numeric `extraKeys` never call this — they go straight to `onChange`). The one place NumPad
36
+ * hands control back to the app: it cannot know what a key like `{ value: 'exact' }` should
37
+ * write into the buffer, only that it was pressed.
38
+ */
39
+ onAction?: (value: string) => void;
40
+ /** Disables every key at once — real `aria-disabled`, and a press does nothing, not just a
41
+ * colour change. Typical use: no line selected yet to type a quantity into. */
42
+ isDisabled?: boolean;
43
+ size?: 'md' | 'lg';
44
+ className?: string;
45
+ style?: React.CSSProperties;
46
+ }
47
+ /**
48
+ * An on-screen numeric keypad for a counter operated hands-on-keyboard: a POS quantity or an
49
+ * amount tendered, typed without looking down at the screen.
50
+ *
51
+ * Two defects the design it replaces had, and the reason both traps are closed here rather than
52
+ * left to each product: every press works from the physical keyboard as well as a click (see
53
+ * {@link useNumPadKeyboard}), and `isDisabled` is real — a native disabled `<button>`, not a
54
+ * class name a press still gets through.
55
+ *
56
+ * A screen with two of these mounted at once — a quantity keypad in a cart panel, an amount
57
+ * keypad in the payment overlay covering it — never has both answer the same keystroke either:
58
+ * see {@link useNumPadKeyboard} for how the backgrounded one recognises that on its own.
59
+ */
60
+ export declare function NumPad({ 'aria-label': ariaLabel, target, value, onChange, extraKeys, onAction, isDisabled, size, className, style, }: NumPadProps): React.JSX.Element;
61
+ //# sourceMappingURL=NumPad.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NumPad.d.ts","sourceRoot":"","sources":["../../../src/components/patterns/NumPad.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,MAAM,WAAW,SAAS;IACxB;;;;;;OAMG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;wEACoE;IACpE,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B;0DACsD;IACtD,YAAY,EAAE,MAAM,CAAC;IACrB;;qBAEiB;IACjB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB;;kFAE8E;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC;yFACqF;IACrF,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;oFACgF;IAChF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAyED;;;;;;;;;;;;GAYG;AACH,wBAAgB,MAAM,CAAC,EACrB,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAc,EAAE,QAAQ,EAC1E,UAAU,EAAE,IAAW,EAAE,SAAS,EAAE,KAAK,GAC1C,EAAE,WAAW,qBAuCb"}
@@ -886,6 +886,15 @@
886
886
  .pire-cp-hint{display:flex;align-items:center;gap:var(--sp-1);font:var(--type-caption);color:var(--text-secondary)}
887
887
  .pire-cp-loading{padding:var(--sp-1) var(--sp-4);font:var(--type-caption);color:var(--text-secondary);border-block-end:1px solid var(--border-subtle)}
888
888
 
889
+ /* ---- NumPad --------------------------------------------------------------- */
890
+ .pire-numpad{display:flex;flex-direction:column;gap:var(--sp-3)}
891
+ .pire-numpad-target{font:var(--type-body-strong);color:var(--text-secondary)}
892
+ .pire-numpad-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-2)}
893
+ /* Larger than a form button's own type on purpose: this grid is read and pressed without looking
894
+ closely at the screen, so the digits carry more weight than `.pire-btn`'s default. */
895
+ .pire-numpad-key{font:var(--type-h3)}
896
+ .pire-numpad-key[data-span="2"]{grid-column:span 2}
897
+
889
898
  /* ---- Reduced motion --------------------------------------------------- */
890
899
  @media (prefers-reduced-motion: reduce){.pire-modal,.pire-toast,.pire-popover,.pire-tooltip,.pire-sidepanel,.pire-cp-overlay,.pire-cp-modal{animation:none}
891
900
  /* The skeleton also drops its background sweep, not just the animation: an infinite shimmer is
@@ -133,6 +133,10 @@ export interface PireMessages {
133
133
  chartNoValue: string;
134
134
  /** Shown in place of the plot when a chart has nothing to draw. */
135
135
  chartEmpty: string;
136
+ /** Accessible name of NumPad's clear key. Its visible glyph is "C". */
137
+ numPadClear: string;
138
+ /** Accessible name of NumPad's backspace key. Its visible glyph is "⌫". */
139
+ numPadBackspace: string;
136
140
  }
137
141
  export declare const enMessages: PireMessages;
138
142
  export declare const esMessages: PireMessages;
@@ -133,6 +133,10 @@ export interface PireMessages {
133
133
  chartNoValue: string;
134
134
  /** Shown in place of the plot when a chart has nothing to draw. */
135
135
  chartEmpty: string;
136
+ /** Accessible name of NumPad's clear key. Its visible glyph is "C". */
137
+ numPadClear: string;
138
+ /** Accessible name of NumPad's backspace key. Its visible glyph is "⌫". */
139
+ numPadBackspace: string;
136
140
  }
137
141
  export declare const enMessages: PireMessages;
138
142
  export declare const esMessages: PireMessages;
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/i18n/messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAY;IAC3B,iCAAiC;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,8EAA8E;IAC9E,WAAW,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,iBAAiB,EAAE,MAAM,CAAC;IAE1B,qEAAqE;IACrE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qDAAqD;IACrD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oDAAoD;IACpD,gBAAgB,EAAE,MAAM,CAAC;IACzB,6FAA6F;IAC7F,mBAAmB,EAAE,MAAM,CAAC;IAC5B,8EAA8E;IAC9E,cAAc,EAAE,MAAM,CAAC;IAEvB,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,cAAc,EAAE,MAAM,CAAC;IAEvB,6DAA6D;IAC7D,oBAAoB,EAAE,MAAM,CAAC;IAC7B,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,gBAAgB,EAAE,MAAM,CAAC;IAEzB,kEAAkE;IAClE;oGACgG;IAChG,WAAW,EAAE,MAAM,CAAC;IAEpB,uBAAuB,EAAE,MAAM,CAAC;IAChC,mEAAmE;IACnE,eAAe,EAAE,MAAM,CAAC;IAExB,qEAAqE;IACrE,sBAAsB,EAAE,MAAM,CAAC;IAC/B,uBAAuB,EAAE,MAAM,CAAC;IAChC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,6DAA6D;IAC7D,qBAAqB,EAAE,MAAM,CAAC;IAE9B,oDAAoD;IACpD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAE5B,kEAAkE;IAClE,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;IAEnB,yEAAyE;IACzE,yBAAyB,EAAE,MAAM,CAAC;IAClC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,qFAAqF;IACrF,uBAAuB,EAAE,MAAM,CAAC;IAChC,uEAAuE;IACvE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,yDAAyD;IACzD,qBAAqB,EAAE,MAAM,CAAC;IAC9B,iEAAiE;IACjE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gDAAgD;IAChD,gCAAgC,EAAE,MAAM,CAAC;IACzC,6CAA6C;IAC7C,oBAAoB,EAAE,MAAM,CAAC;IAC7B,uDAAuD;IACvD,qBAAqB,EAAE,MAAM,CAAC;IAE9B,mDAAmD;IACnD,eAAe,EAAE,MAAM,CAAC;IACxB,wFAAwF;IACxF,eAAe,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;IAE9B,0FAA0F;IAC1F,YAAY,EAAE,MAAM,CAAC;IACrB;wDACoD;IACpD,cAAc,EAAE,MAAM,CAAC;IAEvB,2EAA2E;IAC3E,gBAAgB,EAAE,MAAM,CAAC;IACzB,yCAAyC;IACzC,gBAAgB,EAAE,MAAM,CAAC;IACzB,uDAAuD;IACvD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,6CAA6C;IAC7C,gBAAgB,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qCAAqC;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,eAAe,EAAE,MAAM,CAAC;IACxB,8EAA8E;IAC9E,aAAa,EAAE,MAAM,CAAC;IAEtB,4CAA4C;IAC5C,gBAAgB,EAAE,MAAM,CAAC;IACzB,wEAAwE;IACxE,qBAAqB,EAAE,MAAM,CAAC;IAC9B,uDAAuD;IACvD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,2CAA2C;IAC3C,kBAAkB,EAAE,MAAM,CAAC;IAE3B,kGAAkG;IAClG,gBAAgB,EAAE,MAAM,CAAC;IAEzB,wCAAwC;IACxC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,qDAAqD;IACrD,yBAAyB,EAAE,MAAM,CAAC;IAClC,0CAA0C;IAC1C,yBAAyB,EAAE,MAAM,CAAC;IAClC,iDAAiD;IACjD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,uDAAuD;IACvD,qBAAqB,EAAE,MAAM,CAAC;IAC9B,+CAA+C;IAC/C,0BAA0B,EAAE,MAAM,CAAC;IACnC,0CAA0C;IAC1C,wBAAwB,EAAE,MAAM,CAAC;IACjC,wCAAwC;IACxC,uBAAuB,EAAE,MAAM,CAAC;IAEhC,8DAA8D;IAC9D,mBAAmB,EAAE,MAAM,CAAC;IAC5B,qGAAqG;IACrG,YAAY,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,UAAU,EAAE,YAgFxB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,YAgFxB,CAAC"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/i18n/messages.ts"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -77,6 +77,7 @@ __export(src_exports, {
77
77
  MenuSeparator: () => MenuSeparator,
78
78
  MenuTrigger: () => import_react_aria_components36.MenuTrigger,
79
79
  MultiComboBox: () => MultiComboBox,
80
+ NumPad: () => NumPad,
80
81
  NumberField: () => NumberField,
81
82
  ObjectHeader: () => ObjectHeader,
82
83
  PageBand: () => PageBand,
@@ -914,7 +915,9 @@ var enMessages = {
914
915
  commandPaletteHintClose: "close",
915
916
  chartCategoryHeader: "Category",
916
917
  chartNoValue: "No data",
917
- chartEmpty: "No data for this period"
918
+ chartEmpty: "No data for this period",
919
+ numPadClear: "Clear",
920
+ numPadBackspace: "Remove last digit"
918
921
  };
919
922
  var esMessages = {
920
923
  filterBarLabel: "Filtros",
@@ -980,7 +983,9 @@ var esMessages = {
980
983
  commandPaletteHintClose: "cerrar",
981
984
  chartCategoryHeader: "Categor\xEDa",
982
985
  chartNoValue: "Sin datos",
983
- chartEmpty: "Sin datos para este per\xEDodo"
986
+ chartEmpty: "Sin datos para este per\xEDodo",
987
+ numPadClear: "Limpiar",
988
+ numPadBackspace: "Borrar \xFAltimo d\xEDgito"
984
989
  };
985
990
 
986
991
  // src/i18n/PireIntlProvider.tsx
@@ -4139,10 +4144,125 @@ function EmptyState({ icon = "file-text", title, action, compact, children, clas
4139
4144
  ] });
4140
4145
  }
4141
4146
 
4142
- // src/components/patterns/FileDropZone.tsx
4147
+ // src/components/patterns/NumPad.tsx
4143
4148
  var React28 = __toESM(require("react"), 1);
4144
- var import_react_aria_components35 = require("react-aria-components");
4145
4149
  var import_jsx_runtime65 = require("react/jsx-runtime");
4150
+ var BASE_KEYS = [
4151
+ { value: "7" },
4152
+ { value: "8" },
4153
+ { value: "9" },
4154
+ { value: "clear", label: "C" },
4155
+ { value: "4" },
4156
+ { value: "5" },
4157
+ { value: "6" },
4158
+ { value: "backspace", label: "\u232B" },
4159
+ { value: "1" },
4160
+ { value: "2" },
4161
+ { value: "3" },
4162
+ { value: "0" }
4163
+ ];
4164
+ var isInsertable = (value) => /^[0-9]+$/.test(value);
4165
+ function useNumPadKeyboard(onKey, isDisabled, containerRef) {
4166
+ const handler = React28.useRef(onKey);
4167
+ handler.current = onKey;
4168
+ React28.useEffect(() => {
4169
+ if (isDisabled) return;
4170
+ const isEditingElsewhere = () => {
4171
+ const el = document.activeElement;
4172
+ if (!el) return false;
4173
+ const tag = el.tagName;
4174
+ return tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || el.hasAttribute("contenteditable");
4175
+ };
4176
+ const isBackgroundedByAnOverlay = () => containerRef.current?.closest("[inert]") != null;
4177
+ const onKeyDown = (event) => {
4178
+ if (event.metaKey || event.ctrlKey || event.altKey) return;
4179
+ if (isEditingElsewhere() || isBackgroundedByAnOverlay()) return;
4180
+ if (event.key >= "0" && event.key <= "9") {
4181
+ handler.current(event.key);
4182
+ return;
4183
+ }
4184
+ if (event.key === "Backspace") {
4185
+ handler.current("backspace");
4186
+ return;
4187
+ }
4188
+ if (event.key === "Escape") {
4189
+ handler.current("clear");
4190
+ return;
4191
+ }
4192
+ };
4193
+ document.addEventListener("keydown", onKeyDown);
4194
+ return () => document.removeEventListener("keydown", onKeyDown);
4195
+ }, [isDisabled, containerRef]);
4196
+ }
4197
+ function NumPad({
4198
+ "aria-label": ariaLabel,
4199
+ target,
4200
+ value,
4201
+ onChange,
4202
+ extraKeys = [],
4203
+ onAction,
4204
+ isDisabled,
4205
+ size = "md",
4206
+ className,
4207
+ style
4208
+ }) {
4209
+ const msg = usePireMessages();
4210
+ const containerRef = React28.useRef(null);
4211
+ const applyKey = React28.useCallback((key) => {
4212
+ if (isDisabled) return;
4213
+ if (key.value === "backspace") {
4214
+ onChange(value.slice(0, -1));
4215
+ return;
4216
+ }
4217
+ if (key.value === "clear") {
4218
+ onChange("");
4219
+ return;
4220
+ }
4221
+ if (isInsertable(key.value)) {
4222
+ onChange(value + key.value);
4223
+ return;
4224
+ }
4225
+ onAction?.(key.value);
4226
+ }, [isDisabled, value, onChange, onAction]);
4227
+ useNumPadKeyboard((keyValue) => applyKey({ value: keyValue }), isDisabled, containerRef);
4228
+ const keys = [...BASE_KEYS, ...extraKeys];
4229
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
4230
+ "div",
4231
+ {
4232
+ ref: containerRef,
4233
+ className: cx("pire-numpad", className),
4234
+ style,
4235
+ "data-size": size,
4236
+ "data-disabled": isDisabled ? "true" : void 0,
4237
+ children: [
4238
+ target !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: "pire-numpad-target", role: "status", "aria-live": "polite", children: target }) : null,
4239
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: "pire-numpad-grid", role: "group", "aria-label": ariaLabel, children: keys.map((key) => {
4240
+ const accessibleLabel = key.value === "backspace" ? msg.numPadBackspace : key.value === "clear" ? msg.numPadClear : void 0;
4241
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
4242
+ Button,
4243
+ {
4244
+ variant: "secondary",
4245
+ size,
4246
+ fullWidth: true,
4247
+ className: "pire-numpad-key",
4248
+ "data-span": key.span === 2 ? "2" : void 0,
4249
+ isDisabled,
4250
+ "aria-label": accessibleLabel,
4251
+ onPress: () => applyKey(key),
4252
+ children: key.label ?? key.value
4253
+ },
4254
+ key.value
4255
+ );
4256
+ }) })
4257
+ ]
4258
+ }
4259
+ );
4260
+ }
4261
+
4262
+ // src/components/patterns/FileDropZone.tsx
4263
+ var React29 = __toESM(require("react"), 1);
4264
+ var import_react_aria_components35 = require("react-aria-components");
4265
+ var import_jsx_runtime66 = require("react/jsx-runtime");
4146
4266
  var isImage2 = (file) => file.type.startsWith("image/");
4147
4267
  function FileDropZone({
4148
4268
  label,
@@ -4170,10 +4290,10 @@ function FileDropZone({
4170
4290
  ...rest
4171
4291
  }) {
4172
4292
  const msg = usePireMessages();
4173
- const [uncontrolled, setUncontrolled] = React28.useState(defaultValue ?? []);
4293
+ const [uncontrolled, setUncontrolled] = React29.useState(defaultValue ?? []);
4174
4294
  const files = value ?? uncontrolled;
4175
- const created = React28.useRef([]);
4176
- React28.useEffect(() => () => {
4295
+ const created = React29.useRef([]);
4296
+ React29.useEffect(() => () => {
4177
4297
  for (const url of created.current) URL.revokeObjectURL(url);
4178
4298
  }, []);
4179
4299
  const commit = (next) => {
@@ -4193,12 +4313,12 @@ function FileDropZone({
4193
4313
  commit(allowsMultiple ? [...files, ...wrapped] : wrapped.slice(0, 1));
4194
4314
  };
4195
4315
  const remove = (target) => commit(files.filter((f) => f.file !== target));
4196
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: cx("pire-field", className), style, "data-full-width": String(fullWidth), ...rest, children: [
4197
- label ? /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("span", { className: "pire-field-label", children: [
4316
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: cx("pire-field", className), style, "data-full-width": String(fullWidth), ...rest, children: [
4317
+ label ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "pire-field-label", children: [
4198
4318
  label,
4199
- isRequired ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
4319
+ isRequired ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
4200
4320
  ] }) : null,
4201
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
4321
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
4202
4322
  import_react_aria_components35.DropZone,
4203
4323
  {
4204
4324
  className: "pire-dropzone",
@@ -4212,25 +4332,25 @@ function FileDropZone({
4212
4332
  accept(dropped);
4213
4333
  },
4214
4334
  children: [
4215
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(Icon, { name: "download", size: 24, className: "pire-dropzone-icon" }),
4216
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "pire-dropzone-prompt", children: promptLabel ?? msg.fileDropZonePrompt }),
4217
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
4335
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Icon, { name: "download", size: 24, className: "pire-dropzone-icon" }),
4336
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "pire-dropzone-prompt", children: promptLabel ?? msg.fileDropZonePrompt }),
4337
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
4218
4338
  import_react_aria_components35.FileTrigger,
4219
4339
  {
4220
4340
  acceptedFileTypes,
4221
4341
  allowsMultiple,
4222
4342
  onSelect: (list) => accept(list ? [...list] : []),
4223
- children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(Button, { variant: "secondary", isDisabled: isDisabled || isReadOnly, children: msg.fileUploadChoose })
4343
+ children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Button, { variant: "secondary", isDisabled: isDisabled || isReadOnly, children: msg.fileUploadChoose })
4224
4344
  }
4225
4345
  )
4226
4346
  ]
4227
4347
  }
4228
4348
  ),
4229
- files.length ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("li", { className: "pire-fileupload-item", children: [
4230
- previewUrl ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
4231
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "pire-fileupload-name", children: file.name }),
4232
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
4233
- isDisabled || isReadOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
4349
+ files.length ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("li", { className: "pire-fileupload-item", children: [
4350
+ previewUrl ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
4351
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "pire-fileupload-name", children: file.name }),
4352
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
4353
+ isDisabled || isReadOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
4234
4354
  IconButton,
4235
4355
  {
4236
4356
  icon: "x",
@@ -4240,9 +4360,9 @@ function FileDropZone({
4240
4360
  }
4241
4361
  )
4242
4362
  ] }, `${file.name}-${file.size}-${file.lastModified}`)) }) : null,
4243
- uploadProgress != null ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
4244
- description ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "pire-field-hint", children: description }) : null,
4245
- isInvalid && errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "pire-field-error", children: errorMessage }) : null
4363
+ uploadProgress != null ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
4364
+ description ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "pire-field-hint", children: description }) : null,
4365
+ isInvalid && errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "pire-field-error", children: errorMessage }) : null
4246
4366
  ] });
4247
4367
  }
4248
4368
 
@@ -4298,6 +4418,7 @@ var import_react_aria_components37 = require("react-aria-components");
4298
4418
  MenuSeparator,
4299
4419
  MenuTrigger,
4300
4420
  MultiComboBox,
4421
+ NumPad,
4301
4422
  NumberField,
4302
4423
  ObjectHeader,
4303
4424
  PageBand,