iryx-ui 0.3.0 → 0.4.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.
package/README.md CHANGED
@@ -262,8 +262,9 @@ app.use(createIryxUi({ unstyled: true }))
262
262
  | `IForm` | Validating form wrapper — any Standard Schema validator, or your own function |
263
263
  | `IFormField` | Label, description, hint, help and error text around a control |
264
264
  | `IInput` | Text field with `sm`/`md`/`lg` sizes, `invalid` state, `v-model` |
265
+ | `INumberInput` | Decimal-safe numeric field — the model is a **string**, with `min`/`max`/`step`, `precision` and locale-aware display |
265
266
  | `ITextarea` | Multi-line field with matching sizes and `invalid` state |
266
- | `ILabel` | Field label with optional `required` asterisk, indented to line up with the control's text |
267
+ | `ILabel` | Field label with optional `required` asterisk |
267
268
  | `ICheckbox` | Tri-state checkbox (`true` / `false` / `'indeterminate'`), optional `label` + `description` |
268
269
  | `ISelect` | Listbox with keyboard nav and typeahead, driven by an `items` array |
269
270
  | `IRadioGroup` | Radio list with labels wired up automatically; items take a `description` |
@@ -405,6 +406,45 @@ const framework = ref('vue')
405
406
 
406
407
  `ISelect` and `IRadioGroup` accept plain strings or `{ label, value, disabled }` objects. Both also take a default slot if you'd rather compose the Reka primitives yourself.
407
408
 
409
+ ### Numbers and money
410
+
411
+ `INumberInput` never turns your value into a `number`. The model is a decimal
412
+ **string**, because binary floating point cannot represent decimal money —
413
+ `0.1 + 0.2` is `0.30000000000000004`, and `10.00` becomes `10`. Values are
414
+ added, compared and rounded with `BigInt` internally, so precision survives
415
+ regardless of magnitude.
416
+
417
+ ```vue
418
+ <script setup lang="ts">
419
+ import { ref } from 'vue'
420
+
421
+ // A string, and it stays one.
422
+ const amount = ref('1234.56')
423
+ </script>
424
+
425
+ <template>
426
+ <INumberInput v-model="amount" locale="sl" :precision="2" step="0.01" min="0" />
427
+ </template>
428
+ ```
429
+
430
+ `locale` affects the **display only** — `sl` shows `1.234,56` while the model
431
+ stays `"1234.56"`. Typing in the locale's own format works too. While the field
432
+ is focused it shows the canonical value so separators can't fight your typing.
433
+
434
+ `precision` fixes the number of decimal places, rounding half-up, and preserves
435
+ trailing zeros (`"10.00"` stays `"10.00"`). `min`, `max` and `step` are decimal
436
+ strings as well, and stepping is exact: `0.1 + 0.2` gives `"0.3"`.
437
+
438
+ The underlying helpers are exported if you need them elsewhere:
439
+
440
+ ```ts
441
+ import { addDecimals, compareDecimals, roundDecimal } from 'iryx-ui'
442
+
443
+ addDecimals('0.1', '0.2') // '0.3'
444
+ roundDecimal('1.005', 2) // '1.01'
445
+ compareDecimals('1.10', '1.1') // 0
446
+ ```
447
+
408
448
  ### Validated forms
409
449
 
410
450
  `IForm` handles client-side validation. It accepts any [Standard Schema](https://standardschema.dev) validator — Zod 3.24+, Valibot, ArkType — so Iryx doesn't depend on a validation library. Wrap each control in an `IFormField` with a `name` matching the schema path and errors wire themselves up.
@@ -456,25 +496,6 @@ The control inside a field automatically inherits its `id`, invalid styling and
456
496
 
457
497
  **Server errors and manual control** — grab a template ref to the form and call `validate()`, `clear(name?)` or `setErrors()`. `IFormField` also takes a plain `error` prop that bypasses validation entirely.
458
498
 
459
- ### Label alignment
460
-
461
- `ILabel` and `IFormField` indent their text so it lines up with the control's
462
- text rather than its outer edge, putting the label directly above the
463
- placeholder. The offset matches the input's horizontal padding — `sm` 10px,
464
- `md` 12px, `lg` 16px — so pass the same size you gave the control:
465
-
466
- ```vue
467
- <template>
468
- <ILabel for="amount" indent="lg">
469
- Amount
470
- </ILabel>
471
- <IInput id="amount" size="lg" />
472
- </template>
473
- ```
474
-
475
- Use `indent="none"` when the label wraps its control, as with a checkbox, since
476
- there is no text to line up with.
477
-
478
499
  ### Labels and descriptions
479
500
 
480
501
  `ICheckbox` and `ISwitch` render bare by default. Give them a `label` and/or `description` and they render a wired-up layout instead — the text is clickable, and the description is linked with `aria-describedby`. `IRadioGroup` items take a `description` too.
@@ -3,5 +3,5 @@
3
3
  * Consumed by the Vue plugin (global registration) and the Nuxt module
4
4
  * (auto-imports). Keep in sync with `src/components/index.ts`.
5
5
  */
6
- export declare const componentNames: readonly ["Alert", "App", "Badge", "Breadcrumb", "Button", "ButtonGroup", "Card", "Checkbox", "ConfirmDialog", "Dialog", "DropdownMenu", "EmptyState", "Form", "FormField", "Input", "Label", "Pagination", "Progress", "RadioGroup", "Select", "Separator", "Skeleton", "Stat", "Stepper", "Switch", "Tabs", "Textarea", "Toaster", "Tooltip"];
6
+ export declare const componentNames: readonly ["Alert", "App", "Badge", "Breadcrumb", "Button", "ButtonGroup", "Card", "Checkbox", "ConfirmDialog", "Dialog", "DropdownMenu", "EmptyState", "Form", "FormField", "Input", "Label", "NumberInput", "Pagination", "Progress", "RadioGroup", "Select", "Separator", "Skeleton", "Stat", "Stepper", "Switch", "Tabs", "Textarea", "Toaster", "Tooltip"];
7
7
  export type ComponentName = (typeof componentNames)[number];
@@ -11,15 +11,6 @@ export interface FormFieldProps {
11
11
  required?: boolean;
12
12
  /** Force an error message, bypassing the form's validation. */
13
13
  error?: string;
14
- /**
15
- * Indent the label, description, error and help text so they line up with
16
- * the control's own text rather than its outer edge.
17
- *
18
- * The values match the input's horizontal padding, so pass the same size you
19
- * gave the control. Use `none` for controls that draw their own label, like
20
- * a checkbox or switch.
21
- */
22
- indent?: 'none' | 'sm' | 'md' | 'lg';
23
14
  /** Skip built-in classes; you take over styling entirely. */
24
15
  unstyled?: boolean;
25
16
  class?: string;
@@ -2,12 +2,6 @@ import type { LabelProps as RekaLabelProps } from 'reka-ui';
2
2
  export interface LabelProps extends RekaLabelProps {
3
3
  /** Append a red asterisk to mark the associated field as required. */
4
4
  required?: boolean;
5
- /**
6
- * Indent the label to line up with the control's text rather than its outer
7
- * edge. Match it to the control's size; use `none` when the label wraps its
8
- * control, as with a checkbox.
9
- */
10
- indent?: 'none' | 'sm' | 'md' | 'lg';
11
5
  /** Skip built-in classes; you take over styling entirely. */
12
6
  unstyled?: boolean;
13
7
  class?: string;
@@ -0,0 +1,63 @@
1
+ export interface NumberInputProps {
2
+ /** Smallest allowed value, as a decimal string. */
3
+ min?: string;
4
+ /** Largest allowed value, as a decimal string. */
5
+ max?: string;
6
+ /** Amount the stepper adds or subtracts, as a decimal string. */
7
+ step?: string;
8
+ /** Fixed decimal places. Values are rounded half-up to this scale. */
9
+ precision?: number;
10
+ /**
11
+ * Locale used for the *display* only — `sl` shows `1.234,56`. The model
12
+ * stays canonical (`"1234.56"`) whatever the locale.
13
+ */
14
+ locale?: string;
15
+ /** Show the stacked increment/decrement controls. */
16
+ stepper?: boolean;
17
+ size?: 'sm' | 'md' | 'lg';
18
+ placeholder?: string;
19
+ disabled?: boolean;
20
+ required?: boolean;
21
+ /** Mark the field as invalid — styles the border and ring red. */
22
+ invalid?: boolean;
23
+ id?: string;
24
+ /** Accessible names for the stepper controls — override for non-English apps. */
25
+ incrementLabel?: string;
26
+ decrementLabel?: string;
27
+ /** Skip built-in classes; you take over styling entirely. */
28
+ unstyled?: boolean;
29
+ class?: string;
30
+ /** Override classes per slot, e.g. `{ step: 'px-2' }`. */
31
+ ui?: {
32
+ root?: string;
33
+ input?: string;
34
+ stepper?: string;
35
+ step?: string;
36
+ };
37
+ }
38
+ type __VLS_Props = NumberInputProps;
39
+ type __VLS_ModelProps = {
40
+ /**
41
+ * The model is a decimal **string**, never a number.
42
+ *
43
+ * Money in a finance app is computed with decimal arithmetic; coercing to a
44
+ * float here would silently lose precision before the value ever reached the
45
+ * caller. An empty string means "no value".
46
+ */
47
+ modelValue?: string;
48
+ };
49
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
50
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
51
+ "update:modelValue": (value: string) => any;
52
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
53
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
54
+ }>, {
55
+ unstyled: boolean;
56
+ step: string;
57
+ invalid: boolean;
58
+ stepper: boolean;
59
+ incrementLabel: string;
60
+ decrementLabel: string;
61
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
62
+ declare const _default: typeof __VLS_export;
63
+ export default _default;
@@ -14,6 +14,7 @@ export { default as Form } from './Form.vue';
14
14
  export { default as FormField } from './FormField.vue';
15
15
  export { default as Input } from './Input.vue';
16
16
  export { default as Label } from './Label.vue';
17
+ export { default as NumberInput } from './NumberInput.vue';
17
18
  export { default as Pagination } from './Pagination.vue';
18
19
  export { default as Progress } from './Progress.vue';
19
20
  export { default as RadioGroup } from './RadioGroup.vue';
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Decimal-string arithmetic, exact by construction.
3
+ *
4
+ * Money is stored and computed as decimal strings — `0.1 + 0.2` in binary
5
+ * floating point is `0.30000000000000004`, which silently corrupts a total.
6
+ * Everything here scales to integers and uses `BigInt`, so a value only ever
7
+ * round-trips through `Number` if the caller asks for it.
8
+ */
9
+ interface Decimal {
10
+ /** Unscaled value: `1234.56` at scale 2 is `123456n`. */
11
+ units: bigint;
12
+ /** Number of decimal places. */
13
+ scale: number;
14
+ }
15
+ /** Parse a canonical decimal string (`-1234.56`). Returns undefined if invalid. */
16
+ export declare function parseDecimal(value: string): Decimal | undefined;
17
+ /** Render a Decimal back to a canonical string. */
18
+ export declare function formatDecimal({ units, scale }: Decimal): string;
19
+ /** `-1` if a < b, `0` if equal, `1` if a > b. */
20
+ export declare function compareDecimals(a: string, b: string): number;
21
+ /** Exact addition. `addDecimals('0.1', '0.2')` is `'0.3'`, not `'0.30000000000000004'`. */
22
+ export declare function addDecimals(a: string, b: string): string | undefined;
23
+ /** Round half-up to a fixed number of decimal places. */
24
+ export declare function roundDecimal(value: string, precision: number): string | undefined;
25
+ /** Constrain a value to a range, comparing exactly. */
26
+ export declare function clampDecimal(value: string, min?: string, max?: string): string;
27
+ /** Whether a string is a well-formed decimal. */
28
+ export declare function isDecimal(value: string): boolean;
29
+ /** The separators a locale uses, e.g. `.`/`,` for `en`, `,`/`.` for `sl`. */
30
+ export declare function localeSeparators(locale: string): {
31
+ decimal: string;
32
+ group: string;
33
+ };
34
+ /**
35
+ * Render a canonical decimal for display, e.g. `"1234.56"` as `1.234,56` in
36
+ * `sl`. Formatting goes through the digits, never `Number`, so a value too
37
+ * large for a float still displays exactly.
38
+ */
39
+ export declare function formatForLocale(value: string, locale: string, precision?: number): string;
40
+ /**
41
+ * Render a canonical decimal for *editing*: the locale's decimal separator,
42
+ * but no grouping.
43
+ *
44
+ * Editing must not show the canonical `1234.56` in a locale where `.` groups
45
+ * digits — parsing that back would read it as `123456`.
46
+ */
47
+ export declare function toEditable(value: string, locale?: string): string;
48
+ /**
49
+ * Turn typed input into a canonical decimal, accepting the locale's
50
+ * separators. `1.234,56` in `sl` becomes `1234.56`.
51
+ */
52
+ export declare function parseFromLocale(input: string, locale: string): string | undefined;
53
+ export {};
package/dist/index.d.ts CHANGED
@@ -17,6 +17,7 @@ export type { FormProps } from './components/Form.vue';
17
17
  export type { FormFieldProps } from './components/FormField.vue';
18
18
  export type { InputProps } from './components/Input.vue';
19
19
  export type { LabelProps } from './components/Label.vue';
20
+ export type { NumberInputProps } from './components/NumberInput.vue';
20
21
  export type { PaginationProps } from './components/Pagination.vue';
21
22
  export type { ProgressProps } from './components/Progress.vue';
22
23
  export type { RadioGroupItemOption, RadioGroupProps } from './components/RadioGroup.vue';
@@ -33,6 +34,7 @@ export type { TooltipProps } from './components/Tooltip.vue';
33
34
  export * from './composables/appearance';
34
35
  export * from './composables/button-group';
35
36
  export * from './composables/confirm';
37
+ export * from './composables/decimal';
36
38
  export * from './composables/dropdown-menu';
37
39
  export * from './composables/form';
38
40
  export * from './composables/toast';
package/dist/index.js CHANGED
@@ -34,31 +34,34 @@ import q from "./packages/iryx-ui/src/components/Label.js";
34
34
  import J from "./packages/iryx-ui/src/components/FormField.js";
35
35
  import { fieldBase as Y, inputTheme as X, textareaTheme as Z } from "./packages/iryx-ui/src/theme/input.js";
36
36
  import Q from "./packages/iryx-ui/src/components/Input.js";
37
- import { paginationTheme as $ } from "./packages/iryx-ui/src/theme/pagination.js";
38
- import ee from "./packages/iryx-ui/src/components/Pagination.js";
39
- import { progressTheme as te } from "./packages/iryx-ui/src/theme/progress.js";
40
- import ne from "./packages/iryx-ui/src/components/Progress.js";
41
- import { radioGroupTheme as re } from "./packages/iryx-ui/src/theme/radio-group.js";
42
- import ie from "./packages/iryx-ui/src/components/RadioGroup.js";
43
- import { selectTheme as ae } from "./packages/iryx-ui/src/theme/select.js";
44
- import oe from "./packages/iryx-ui/src/components/Select.js";
45
- import { separatorTheme as se } from "./packages/iryx-ui/src/theme/separator.js";
46
- import ce from "./packages/iryx-ui/src/components/Separator.js";
47
- import { skeletonTheme as le } from "./packages/iryx-ui/src/theme/skeleton.js";
48
- import ue from "./packages/iryx-ui/src/components/Skeleton.js";
49
- import { statTheme as de } from "./packages/iryx-ui/src/theme/stat.js";
50
- import fe from "./packages/iryx-ui/src/components/Stat.js";
51
- import { stepperTheme as pe } from "./packages/iryx-ui/src/theme/stepper.js";
52
- import me from "./packages/iryx-ui/src/components/Stepper.js";
53
- import { switchTheme as he } from "./packages/iryx-ui/src/theme/switch.js";
54
- import ge from "./packages/iryx-ui/src/components/Switch.js";
55
- import { tabsTheme as _e } from "./packages/iryx-ui/src/theme/tabs.js";
56
- import ve from "./packages/iryx-ui/src/components/Tabs.js";
57
- import ye from "./packages/iryx-ui/src/components/Textarea.js";
58
- import { useToast as be, useToastState as xe } from "./packages/iryx-ui/src/composables/toast.js";
59
- import { toastTheme as Se } from "./packages/iryx-ui/src/theme/toast.js";
60
- import Ce from "./packages/iryx-ui/src/components/Toaster.js";
61
- import { tooltipTheme as we } from "./packages/iryx-ui/src/theme/tooltip.js";
62
- import Te from "./packages/iryx-ui/src/components/Tooltip.js";
63
- import { IryxUi as Ee, createIryxUi as De } from "./packages/iryx-ui/src/plugin.js";
64
- export { a as Alert, d as App, p as Badge, h as Breadcrumb, y as Button, x as ButtonGroup, C as Card, T as Checkbox, j as ConfirmDialog, A as Dialog, F as DropdownMenu, L as EmptyState, G as Form, J as FormField, Q as Input, Ee as IryxUi, q as Label, ee as Pagination, ne as Progress, ie as RadioGroup, oe as Select, ce as Separator, ue as Skeleton, fe as Stat, me as Stepper, ge as Switch, ve as Tabs, ye as Textarea, Ce as Toaster, Te as Tooltip, i as alertTheme, c as applyTheme, f as badgeTheme, m as breadcrumbTheme, g as buttonGroupContextKey, b as buttonGroupTheme, v as buttonTheme, S as cardTheme, w as checkboxTheme, l as clearTheme, e as componentNames, De as createIryxUi, t as defaultConfig, k as dialogTheme, M as dropdownMenuTheme, I as emptyStateTheme, Y as fieldBase, R as formContextKey, z as formFieldContextKey, B as getByPath, o as initAppearance, X as inputTheme, n as iryxUiConfigKey, N as isSeparator, V as isStandardSchema, P as isSubmenu, H as issuePath, K as labelTheme, $ as paginationTheme, te as progressTheme, re as radioGroupTheme, E as resolveConfirm, ae as selectTheme, se as separatorTheme, le as skeletonTheme, de as statTheme, pe as stepperTheme, he as switchTheme, _e as tabsTheme, Z as textareaTheme, u as themes, Se as toastTheme, we as tooltipTheme, s as useAppearance, _ as useButtonGroup, D as useConfirm, O as useConfirmState, U as useForm, W as useFormField, r as useIryxUiConfig, be as useToast, xe as useToastState };
37
+ import { addDecimals as $, clampDecimal as ee, compareDecimals as te, formatDecimal as ne, formatForLocale as re, isDecimal as ie, localeSeparators as ae, parseDecimal as oe, parseFromLocale as se, roundDecimal as ce, toEditable as le } from "./packages/iryx-ui/src/composables/decimal.js";
38
+ import { numberInputTheme as ue } from "./packages/iryx-ui/src/theme/number-input.js";
39
+ import de from "./packages/iryx-ui/src/components/NumberInput.js";
40
+ import { paginationTheme as fe } from "./packages/iryx-ui/src/theme/pagination.js";
41
+ import pe from "./packages/iryx-ui/src/components/Pagination.js";
42
+ import { progressTheme as me } from "./packages/iryx-ui/src/theme/progress.js";
43
+ import he from "./packages/iryx-ui/src/components/Progress.js";
44
+ import { radioGroupTheme as ge } from "./packages/iryx-ui/src/theme/radio-group.js";
45
+ import _e from "./packages/iryx-ui/src/components/RadioGroup.js";
46
+ import { selectTheme as ve } from "./packages/iryx-ui/src/theme/select.js";
47
+ import ye from "./packages/iryx-ui/src/components/Select.js";
48
+ import { separatorTheme as be } from "./packages/iryx-ui/src/theme/separator.js";
49
+ import xe from "./packages/iryx-ui/src/components/Separator.js";
50
+ import { skeletonTheme as Se } from "./packages/iryx-ui/src/theme/skeleton.js";
51
+ import Ce from "./packages/iryx-ui/src/components/Skeleton.js";
52
+ import { statTheme as we } from "./packages/iryx-ui/src/theme/stat.js";
53
+ import Te from "./packages/iryx-ui/src/components/Stat.js";
54
+ import { stepperTheme as Ee } from "./packages/iryx-ui/src/theme/stepper.js";
55
+ import De from "./packages/iryx-ui/src/components/Stepper.js";
56
+ import { switchTheme as Oe } from "./packages/iryx-ui/src/theme/switch.js";
57
+ import ke from "./packages/iryx-ui/src/components/Switch.js";
58
+ import { tabsTheme as Ae } from "./packages/iryx-ui/src/theme/tabs.js";
59
+ import je from "./packages/iryx-ui/src/components/Tabs.js";
60
+ import Me from "./packages/iryx-ui/src/components/Textarea.js";
61
+ import { useToast as Ne, useToastState as Pe } from "./packages/iryx-ui/src/composables/toast.js";
62
+ import { toastTheme as Fe } from "./packages/iryx-ui/src/theme/toast.js";
63
+ import Ie from "./packages/iryx-ui/src/components/Toaster.js";
64
+ import { tooltipTheme as Le } from "./packages/iryx-ui/src/theme/tooltip.js";
65
+ import Re from "./packages/iryx-ui/src/components/Tooltip.js";
66
+ import { IryxUi as ze, createIryxUi as Be } from "./packages/iryx-ui/src/plugin.js";
67
+ export { a as Alert, d as App, p as Badge, h as Breadcrumb, y as Button, x as ButtonGroup, C as Card, T as Checkbox, j as ConfirmDialog, A as Dialog, F as DropdownMenu, L as EmptyState, G as Form, J as FormField, Q as Input, ze as IryxUi, q as Label, de as NumberInput, pe as Pagination, he as Progress, _e as RadioGroup, ye as Select, xe as Separator, Ce as Skeleton, Te as Stat, De as Stepper, ke as Switch, je as Tabs, Me as Textarea, Ie as Toaster, Re as Tooltip, $ as addDecimals, i as alertTheme, c as applyTheme, f as badgeTheme, m as breadcrumbTheme, g as buttonGroupContextKey, b as buttonGroupTheme, v as buttonTheme, S as cardTheme, w as checkboxTheme, ee as clampDecimal, l as clearTheme, te as compareDecimals, e as componentNames, Be as createIryxUi, t as defaultConfig, k as dialogTheme, M as dropdownMenuTheme, I as emptyStateTheme, Y as fieldBase, R as formContextKey, z as formFieldContextKey, ne as formatDecimal, re as formatForLocale, B as getByPath, o as initAppearance, X as inputTheme, n as iryxUiConfigKey, ie as isDecimal, N as isSeparator, V as isStandardSchema, P as isSubmenu, H as issuePath, K as labelTheme, ae as localeSeparators, ue as numberInputTheme, fe as paginationTheme, oe as parseDecimal, se as parseFromLocale, me as progressTheme, ge as radioGroupTheme, E as resolveConfirm, ce as roundDecimal, ve as selectTheme, be as separatorTheme, Se as skeletonTheme, we as statTheme, Ee as stepperTheme, Oe as switchTheme, Ae as tabsTheme, Z as textareaTheme, u as themes, le as toEditable, Fe as toastTheme, Le as tooltipTheme, s as useAppearance, _ as useButtonGroup, D as useConfirm, O as useConfirmState, U as useForm, W as useFormField, r as useIryxUiConfig, Ne as useToast, Pe as useToastState };
@@ -1,4 +1,4 @@
1
1
  //#region src/component-names.ts
2
- var e = /* @__PURE__ */ "Alert.App.Badge.Breadcrumb.Button.ButtonGroup.Card.Checkbox.ConfirmDialog.Dialog.DropdownMenu.EmptyState.Form.FormField.Input.Label.Pagination.Progress.RadioGroup.Select.Separator.Skeleton.Stat.Stepper.Switch.Tabs.Textarea.Toaster.Tooltip".split(".");
2
+ var e = /* @__PURE__ */ "Alert.App.Badge.Breadcrumb.Button.ButtonGroup.Card.Checkbox.ConfirmDialog.Dialog.DropdownMenu.EmptyState.Form.FormField.Input.Label.NumberInput.Pagination.Progress.RadioGroup.Select.Separator.Skeleton.Stat.Stepper.Switch.Tabs.Textarea.Toaster.Tooltip".split(".");
3
3
  //#endregion
4
4
  export { e as componentNames };
@@ -15,7 +15,6 @@ var x = ["data-iryx-field"], S = ["id"], C = ["id"], w = ["id"], T = /*@__PURE__
15
15
  help: {},
16
16
  required: { type: Boolean },
17
17
  error: {},
18
- indent: {},
19
18
  unstyled: {
20
19
  type: Boolean,
21
20
  default: void 0
@@ -36,9 +35,9 @@ var x = ["data-iryx-field"], S = ["id"], C = ["id"], w = ["id"], T = /*@__PURE__
36
35
  function A() {
37
36
  !T.name || !E || E.validateOn.value.includes("blur") && E.validateField(T.name);
38
37
  }
39
- let j = e(), M = o(() => T.unstyled ?? j.unstyled), N = o(() => i({ indent: T.indent }));
38
+ let j = e(), M = o(() => T.unstyled ?? j.unstyled), N = i();
40
39
  function P(e, t) {
41
- return M.value ? t : N.value[e]({ class: t });
40
+ return M.value ? t : N[e]({ class: t });
42
41
  }
43
42
  return m(t, {
44
43
  id: o(() => D),
@@ -47,7 +46,7 @@ var x = ["data-iryx-field"], S = ["id"], C = ["id"], w = ["id"], T = /*@__PURE__
47
46
  describedBy: k
48
47
  }), (e, t) => (p(), l("div", {
49
48
  "data-iryx-field": T.name,
50
- class: f(M.value ? T.class : N.value.root({ class: [T.ui?.root, T.class] })),
49
+ class: f(M.value ? T.class : _(N).root({ class: [T.ui?.root, T.class] })),
51
50
  onFocusout: A
52
51
  }, [
53
52
  T.label || T.hint || e.$slots.hint ? (p(), l("div", {
@@ -57,7 +56,6 @@ var x = ["data-iryx-field"], S = ["id"], C = ["id"], w = ["id"], T = /*@__PURE__
57
56
  key: 0,
58
57
  for: _(D),
59
58
  required: T.required,
60
- indent: "none",
61
59
  class: f(T.ui?.label)
62
60
  }, {
63
61
  default: y(() => [u(g(T.label), 1)]),
@@ -7,7 +7,6 @@ var d = /*@__PURE__*/ i({
7
7
  __name: "Label",
8
8
  props: {
9
9
  required: { type: Boolean },
10
- indent: {},
11
10
  unstyled: {
12
11
  type: Boolean,
13
12
  default: void 0
@@ -20,7 +19,6 @@ var d = /*@__PURE__*/ i({
20
19
  setup(i) {
21
20
  let d = i, f = e(), p = n(() => d.unstyled ?? f.unstyled), m = n(() => p.value ? d.class : t({
22
21
  required: d.required,
23
- indent: d.indent,
24
22
  class: d.class
25
23
  }));
26
24
  return (e, t) => (o(), r(c(u), {
@@ -0,0 +1,5 @@
1
+ import e from "./NumberInput.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/components/NumberInput.vue
3
+ var t = e;
4
+ //#endregion
5
+ export { t as default };
@@ -0,0 +1,136 @@
1
+ import { ArrowDown01Icon as e, ArrowUp01Icon as t } from "../../../../node_modules/.pnpm/@hugeicons_core-free-icons@4.2.3/node_modules/@hugeicons/core-free-icons/dist/esm/index.js";
2
+ import { useIryxUiConfig as n } from "../config.js";
3
+ import r from "./Icon.js";
4
+ import { useFormField as i } from "../composables/form.js";
5
+ import { addDecimals as a, clampDecimal as o, compareDecimals as s, formatForLocale as c, isDecimal as l, parseFromLocale as u, roundDecimal as d, toEditable as f } from "../composables/decimal.js";
6
+ import { numberInputTheme as p } from "../theme/number-input.js";
7
+ import { computed as m, createCommentVNode as h, createElementBlock as g, createElementVNode as _, createVNode as v, defineComponent as y, mergeModels as b, normalizeClass as x, openBlock as S, ref as C, unref as w, useModel as T, vModelText as E, watch as D, withDirectives as O, withKeys as k, withModifiers as A } from "vue";
8
+ //#region src/components/NumberInput.vue?vue&type=script&setup=true&lang.ts
9
+ var j = [
10
+ "id",
11
+ "aria-valuenow",
12
+ "aria-valuemin",
13
+ "aria-valuemax",
14
+ "placeholder",
15
+ "disabled",
16
+ "required",
17
+ "aria-invalid",
18
+ "aria-describedby"
19
+ ], M = ["aria-label", "disabled"], N = ["aria-label", "disabled"], P = /*@__PURE__*/ y({
20
+ __name: "NumberInput",
21
+ props: /*@__PURE__*/ b({
22
+ min: {},
23
+ max: {},
24
+ step: { default: "1" },
25
+ precision: {},
26
+ locale: {},
27
+ stepper: {
28
+ type: Boolean,
29
+ default: !0
30
+ },
31
+ size: {},
32
+ placeholder: {},
33
+ disabled: { type: Boolean },
34
+ required: { type: Boolean },
35
+ invalid: {
36
+ type: Boolean,
37
+ default: void 0
38
+ },
39
+ id: {},
40
+ incrementLabel: { default: "Increment" },
41
+ decrementLabel: { default: "Decrement" },
42
+ unstyled: {
43
+ type: Boolean,
44
+ default: void 0
45
+ },
46
+ class: {},
47
+ ui: {}
48
+ }, {
49
+ modelValue: { default: "" },
50
+ modelModifiers: {}
51
+ }),
52
+ emits: ["update:modelValue"],
53
+ setup(y) {
54
+ let b = y, P = T(y, "modelValue"), F = i(), I = m(() => b.id ?? F?.id.value), L = m(() => b.invalid ?? F?.invalid.value ?? !1), R = n(), z = m(() => b.unstyled ?? R.unstyled), B = C(""), V = C(!1);
55
+ function H(e) {
56
+ return e ? b.locale ? c(e, b.locale, b.precision) : b.precision == null ? e : d(e, b.precision) ?? e : "";
57
+ }
58
+ D(() => P.value, (e) => {
59
+ V.value || (B.value = H(e));
60
+ }, { immediate: !0 });
61
+ function U(e) {
62
+ let t = e.trim();
63
+ if (!t) {
64
+ P.value = "", B.value = "";
65
+ return;
66
+ }
67
+ let n = b.locale ? u(t, b.locale) : l(t) ? t : void 0;
68
+ if (n == null) {
69
+ B.value = H(P.value);
70
+ return;
71
+ }
72
+ let r = o(n, b.min, b.max), i = b.precision == null ? r : d(r, b.precision) ?? r;
73
+ P.value = i, B.value = H(i);
74
+ }
75
+ function W() {
76
+ V.value = !0, B.value = f(P.value, b.locale);
77
+ }
78
+ function G() {
79
+ V.value = !1, U(B.value);
80
+ }
81
+ function K(e) {
82
+ let t = a(P.value || "0", e === 1 ? b.step : `-${b.step}`);
83
+ if (t == null) return;
84
+ let n = o(t, b.min, b.max), r = b.precision == null ? n : d(n, b.precision) ?? n;
85
+ P.value = r, B.value = V.value ? f(r, b.locale) : H(r);
86
+ }
87
+ let q = m(() => b.min != null && P.value !== "" && s(P.value, b.min) <= 0), J = m(() => b.max != null && P.value !== "" && s(P.value, b.max) >= 0), Y = m(() => p({
88
+ size: b.size,
89
+ invalid: L.value,
90
+ withStepper: b.stepper
91
+ }));
92
+ function X(e, t) {
93
+ let n = b.ui?.[e];
94
+ return z.value ? [n, t] : Y.value[e]({ class: [n, t] });
95
+ }
96
+ return (n, i) => (S(), g("div", { class: x(X("root")) }, [O(_("input", {
97
+ id: I.value,
98
+ "onUpdate:modelValue": i[0] ||= (e) => B.value = e,
99
+ type: "text",
100
+ inputmode: "decimal",
101
+ autocomplete: "off",
102
+ role: "spinbutton",
103
+ "aria-valuenow": P.value || void 0,
104
+ "aria-valuemin": b.min,
105
+ "aria-valuemax": b.max,
106
+ placeholder: b.placeholder,
107
+ disabled: b.disabled,
108
+ required: b.required,
109
+ "aria-invalid": L.value || void 0,
110
+ "aria-describedby": w(F)?.describedBy.value,
111
+ class: x(z.value ? [b.ui?.input, b.class] : Y.value.input({ class: [b.ui?.input, b.class] })),
112
+ onFocus: W,
113
+ onBlur: G,
114
+ onKeydown: [i[1] ||= k(A((e) => K(1), ["prevent"]), ["up"]), i[2] ||= k(A((e) => K(-1), ["prevent"]), ["down"])]
115
+ }, null, 42, j), [[E, B.value]]), b.stepper ? (S(), g("div", {
116
+ key: 0,
117
+ class: x(X("stepper"))
118
+ }, [_("button", {
119
+ type: "button",
120
+ tabindex: "-1",
121
+ "aria-label": b.incrementLabel,
122
+ disabled: b.disabled || J.value,
123
+ class: x(X("step")),
124
+ onClick: i[3] ||= (e) => K(1)
125
+ }, [v(r, { icon: w(t) }, null, 8, ["icon"])], 10, M), _("button", {
126
+ type: "button",
127
+ tabindex: "-1",
128
+ "aria-label": b.decrementLabel,
129
+ disabled: b.disabled || q.value,
130
+ class: x(X("step")),
131
+ onClick: i[4] ||= (e) => K(-1)
132
+ }, [v(r, { icon: w(e) }, null, 8, ["icon"])], 10, N)], 2)) : h("", !0)], 2));
133
+ }
134
+ });
135
+ //#endregion
136
+ export { P as default };
@@ -15,21 +15,22 @@ import p from "./Form.js";
15
15
  import m from "./Label.js";
16
16
  import h from "./FormField.js";
17
17
  import g from "./Input.js";
18
- import _ from "./Pagination.js";
19
- import v from "./Progress.js";
20
- import y from "./RadioGroup.js";
21
- import b from "./Select.js";
22
- import x from "./Separator.js";
23
- import S from "./Skeleton.js";
24
- import C from "./Stat.js";
25
- import w from "./Stepper.js";
26
- import T from "./Switch.js";
27
- import E from "./Tabs.js";
28
- import D from "./Textarea.js";
29
- import O from "./Toaster.js";
30
- import k from "./Tooltip.js";
18
+ import _ from "./NumberInput.js";
19
+ import v from "./Pagination.js";
20
+ import y from "./Progress.js";
21
+ import b from "./RadioGroup.js";
22
+ import x from "./Select.js";
23
+ import S from "./Separator.js";
24
+ import C from "./Skeleton.js";
25
+ import w from "./Stat.js";
26
+ import T from "./Stepper.js";
27
+ import E from "./Switch.js";
28
+ import D from "./Tabs.js";
29
+ import O from "./Textarea.js";
30
+ import k from "./Toaster.js";
31
+ import A from "./Tooltip.js";
31
32
  //#region src/components/index.ts
32
- var A = /* @__PURE__ */ e({
33
+ var j = /* @__PURE__ */ e({
33
34
  Alert: () => t,
34
35
  App: () => n,
35
36
  Badge: () => r,
@@ -46,19 +47,20 @@ var A = /* @__PURE__ */ e({
46
47
  FormField: () => h,
47
48
  Input: () => g,
48
49
  Label: () => m,
49
- Pagination: () => _,
50
- Progress: () => v,
51
- RadioGroup: () => y,
52
- Select: () => b,
53
- Separator: () => x,
54
- Skeleton: () => S,
55
- Stat: () => C,
56
- Stepper: () => w,
57
- Switch: () => T,
58
- Tabs: () => E,
59
- Textarea: () => D,
60
- Toaster: () => O,
61
- Tooltip: () => k
50
+ NumberInput: () => _,
51
+ Pagination: () => v,
52
+ Progress: () => y,
53
+ RadioGroup: () => b,
54
+ Select: () => x,
55
+ Separator: () => S,
56
+ Skeleton: () => C,
57
+ Stat: () => w,
58
+ Stepper: () => T,
59
+ Switch: () => E,
60
+ Tabs: () => D,
61
+ Textarea: () => O,
62
+ Toaster: () => k,
63
+ Tooltip: () => A
62
64
  });
63
65
  //#endregion
64
- export { A as components_exports };
66
+ export { j as components_exports };
@@ -0,0 +1,79 @@
1
+ //#region src/composables/decimal.ts
2
+ var e = /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/;
3
+ function t(t) {
4
+ let n = t.trim();
5
+ if (!n || !e.test(n)) return;
6
+ let r = n.startsWith("-"), [i = "", a = ""] = n.replace(/^[+-]/, "").split("."), o = `${i || "0"}${a}`, s = BigInt(o || "0");
7
+ return {
8
+ units: r ? -s : s,
9
+ scale: a.length
10
+ };
11
+ }
12
+ function n({ units: e, scale: t }) {
13
+ let n = e < 0n, r = (n ? -e : e).toString().padStart(t + 1, "0"), i = r.slice(0, r.length - t), a = t ? r.slice(r.length - t) : "";
14
+ return `${n ? "-" : ""}${i}${a ? `.${a}` : ""}`;
15
+ }
16
+ function r(e, t) {
17
+ let n = Math.max(e.scale, t.scale), r = (e) => e.units * 10n ** BigInt(n - e.scale);
18
+ return [
19
+ r(e),
20
+ r(t),
21
+ n
22
+ ];
23
+ }
24
+ function i(e, n) {
25
+ let i = t(e), a = t(n);
26
+ if (!i || !a) return NaN;
27
+ let [o, s] = r(i, a);
28
+ return o < s ? -1 : +(o > s);
29
+ }
30
+ function a(e, i) {
31
+ let a = t(e), o = t(i);
32
+ if (!a || !o) return;
33
+ let [s, c, l] = r(a, o);
34
+ return n({
35
+ units: s + c,
36
+ scale: l
37
+ });
38
+ }
39
+ function o(e, r) {
40
+ let i = t(e);
41
+ if (!i) return;
42
+ if (i.scale <= r) return n({
43
+ units: i.units * 10n ** BigInt(r - i.scale),
44
+ scale: r
45
+ });
46
+ let a = 10n ** BigInt(i.scale - r), o = i.units < 0n, s = o ? -i.units : i.units, c = s % a * 2n >= a ? 1n : 0n, l = s / a + c;
47
+ return n({
48
+ units: o ? -l : l,
49
+ scale: r
50
+ });
51
+ }
52
+ function s(e, t, n) {
53
+ return t != null && i(e, t) < 0 ? t : n != null && i(e, n) > 0 ? n : e;
54
+ }
55
+ function c(e) {
56
+ return t(e) !== void 0;
57
+ }
58
+ function l(e) {
59
+ let t = new Intl.NumberFormat(e).formatToParts(12345.6);
60
+ return {
61
+ decimal: t.find((e) => e.type === "decimal")?.value ?? ".",
62
+ group: t.find((e) => e.type === "group")?.value ?? ","
63
+ };
64
+ }
65
+ function u(e, n, r) {
66
+ let i = t(e);
67
+ if (!i) return e;
68
+ let a = o(e, r ?? i.scale) ?? e, [s = "0", c = ""] = a.replace("-", "").split("."), { decimal: u, group: d } = l(n), f = s.replace(/\B(?=(\d{3})+(?!\d))/g, d);
69
+ return `${a.startsWith("-") ? "-" : ""}${f}${c ? `${u}${c}` : ""}`;
70
+ }
71
+ function d(e, t) {
72
+ return !e || !t ? e : e.replace(".", l(t).decimal);
73
+ }
74
+ function f(e, t) {
75
+ let { decimal: n, group: r } = l(t), i = e.trim().replaceAll(r, "").replace(/\s/g, "").replace(n, ".");
76
+ return c(i) ? i : void 0;
77
+ }
78
+ //#endregion
79
+ export { a as addDecimals, s as clampDecimal, i as compareDecimals, n as formatDecimal, u as formatForLocale, c as isDecimal, l as localeSeparators, t as parseDecimal, f as parseFromLocale, o as roundDecimal, d as toEditable };
@@ -1,38 +1,14 @@
1
1
  import { tv as e } from "tailwind-variants";
2
2
  //#region src/theme/form.ts
3
- var t = e({
4
- slots: {
5
- root: "space-y-2",
6
- header: "flex items-center justify-between gap-2",
7
- label: "",
8
- hint: "text-sm leading-none text-muted-foreground",
9
- description: "text-sm leading-snug text-muted-foreground",
10
- control: "",
11
- error: "text-sm leading-snug text-red-500",
12
- help: "text-sm leading-snug text-muted-foreground"
13
- },
14
- variants: { indent: {
15
- none: {},
16
- sm: {
17
- header: "px-2.5",
18
- description: "px-2.5",
19
- error: "px-2.5",
20
- help: "px-2.5"
21
- },
22
- md: {
23
- header: "px-3",
24
- description: "px-3",
25
- error: "px-3",
26
- help: "px-3"
27
- },
28
- lg: {
29
- header: "px-4",
30
- description: "px-4",
31
- error: "px-4",
32
- help: "px-4"
33
- }
34
- } },
35
- defaultVariants: { indent: "md" }
36
- });
3
+ var t = e({ slots: {
4
+ root: "space-y-2",
5
+ header: "flex items-center justify-between gap-2",
6
+ label: "",
7
+ hint: "text-sm leading-none text-muted-foreground",
8
+ description: "text-sm leading-snug text-muted-foreground",
9
+ control: "",
10
+ error: "text-sm leading-snug text-red-500",
11
+ help: "text-sm leading-snug text-muted-foreground"
12
+ } });
37
13
  //#endregion
38
14
  export { t as formFieldTheme };
@@ -2,16 +2,7 @@ import { tv as e } from "tailwind-variants";
2
2
  //#region src/theme/label.ts
3
3
  var t = e({
4
4
  base: "inline-flex items-center gap-1 text-sm leading-none font-medium text-foreground select-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
5
- variants: {
6
- required: { true: "after:text-red-500 after:content-['*']" },
7
- indent: {
8
- none: "",
9
- sm: "ps-2.5",
10
- md: "ps-3",
11
- lg: "ps-4"
12
- }
13
- },
14
- defaultVariants: { indent: "md" }
5
+ variants: { required: { true: "after:text-red-500 after:content-['*']" } }
15
6
  });
16
7
  //#endregion
17
8
  export { t as labelTheme };
@@ -0,0 +1,49 @@
1
+ import { fieldBase as e } from "./input.js";
2
+ import { tv as t } from "tailwind-variants";
3
+ //#region src/theme/number-input.ts
4
+ var n = t({
5
+ slots: {
6
+ root: "relative inline-flex w-full items-stretch",
7
+ input: `flex w-full text-right tabular-nums ${e}`,
8
+ stepper: "absolute inset-y-px end-px flex flex-col justify-center overflow-hidden rounded-e-lg border-s border-border",
9
+ step: "flex flex-1 items-center justify-center px-1.5 text-muted-foreground transition-colors outline-none hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-3"
10
+ },
11
+ variants: {
12
+ size: {
13
+ sm: {
14
+ input: "h-8 px-2.5 text-sm",
15
+ stepper: "w-5"
16
+ },
17
+ md: {
18
+ input: "h-9 px-3 text-sm",
19
+ stepper: "w-6"
20
+ },
21
+ lg: {
22
+ input: "h-10 px-4 text-base",
23
+ stepper: "w-7"
24
+ }
25
+ },
26
+ invalid: { true: { input: "border-red-500 focus-visible:ring-red-500/40" } },
27
+ withStepper: { true: {} }
28
+ },
29
+ compoundVariants: [
30
+ {
31
+ withStepper: !0,
32
+ size: "sm",
33
+ class: { input: "pe-7" }
34
+ },
35
+ {
36
+ withStepper: !0,
37
+ size: "md",
38
+ class: { input: "pe-8" }
39
+ },
40
+ {
41
+ withStepper: !0,
42
+ size: "lg",
43
+ class: { input: "pe-10" }
44
+ }
45
+ ],
46
+ defaultVariants: { size: "md" }
47
+ });
48
+ //#endregion
49
+ export { n as numberInputTheme };
@@ -1,26 +1,30 @@
1
1
  export declare const formFieldTheme: import("tailwind-variants").TVReturnType<{
2
- indent: {
3
- none: {};
4
- sm: {
5
- header: string;
6
- description: string;
7
- error: string;
8
- help: string;
2
+ [key: string]: {
3
+ [key: string]: import("tailwind-variants").ClassValue | {
4
+ root?: import("tailwind-variants").ClassValue;
5
+ description?: import("tailwind-variants").ClassValue;
6
+ label?: import("tailwind-variants").ClassValue;
7
+ header?: import("tailwind-variants").ClassValue;
8
+ error?: import("tailwind-variants").ClassValue;
9
+ hint?: import("tailwind-variants").ClassValue;
10
+ control?: import("tailwind-variants").ClassValue;
11
+ help?: import("tailwind-variants").ClassValue;
9
12
  };
10
- md: {
11
- header: string;
12
- description: string;
13
- error: string;
14
- help: string;
15
- };
16
- lg: {
17
- header: string;
18
- description: string;
19
- error: string;
20
- help: string;
13
+ };
14
+ } | {
15
+ [x: string]: {
16
+ [x: string]: import("tailwind-variants").ClassValue | {
17
+ root?: import("tailwind-variants").ClassValue;
18
+ description?: import("tailwind-variants").ClassValue;
19
+ label?: import("tailwind-variants").ClassValue;
20
+ header?: import("tailwind-variants").ClassValue;
21
+ error?: import("tailwind-variants").ClassValue;
22
+ hint?: import("tailwind-variants").ClassValue;
23
+ control?: import("tailwind-variants").ClassValue;
24
+ help?: import("tailwind-variants").ClassValue;
21
25
  };
22
26
  };
23
- }, {
27
+ } | {}, {
24
28
  root: string;
25
29
  header: string;
26
30
  label: string;
@@ -30,28 +34,19 @@ export declare const formFieldTheme: import("tailwind-variants").TVReturnType<{
30
34
  error: string;
31
35
  help: string;
32
36
  }, undefined, {
33
- indent: {
34
- none: {};
35
- sm: {
36
- header: string;
37
- description: string;
38
- error: string;
39
- help: string;
40
- };
41
- md: {
42
- header: string;
43
- description: string;
44
- error: string;
45
- help: string;
46
- };
47
- lg: {
48
- header: string;
49
- description: string;
50
- error: string;
51
- help: string;
37
+ [key: string]: {
38
+ [key: string]: import("tailwind-variants").ClassValue | {
39
+ root?: import("tailwind-variants").ClassValue;
40
+ description?: import("tailwind-variants").ClassValue;
41
+ label?: import("tailwind-variants").ClassValue;
42
+ header?: import("tailwind-variants").ClassValue;
43
+ error?: import("tailwind-variants").ClassValue;
44
+ hint?: import("tailwind-variants").ClassValue;
45
+ control?: import("tailwind-variants").ClassValue;
46
+ help?: import("tailwind-variants").ClassValue;
52
47
  };
53
48
  };
54
- }, {
49
+ } | {}, {
55
50
  root: string;
56
51
  header: string;
57
52
  label: string;
@@ -60,29 +55,7 @@ export declare const formFieldTheme: import("tailwind-variants").TVReturnType<{
60
55
  control: string;
61
56
  error: string;
62
57
  help: string;
63
- }, import("tailwind-variants").TVReturnType<{
64
- indent: {
65
- none: {};
66
- sm: {
67
- header: string;
68
- description: string;
69
- error: string;
70
- help: string;
71
- };
72
- md: {
73
- header: string;
74
- description: string;
75
- error: string;
76
- help: string;
77
- };
78
- lg: {
79
- header: string;
80
- description: string;
81
- error: string;
82
- help: string;
83
- };
84
- };
85
- }, {
58
+ }, import("tailwind-variants").TVReturnType<unknown, {
86
59
  root: string;
87
60
  header: string;
88
61
  label: string;
@@ -10,6 +10,7 @@ export * from './dropdown-menu';
10
10
  export * from './empty-state';
11
11
  export * from './input';
12
12
  export * from './label';
13
+ export * from './number-input';
13
14
  export * from './pagination';
14
15
  export * from './presets';
15
16
  export * from './progress';
@@ -2,31 +2,13 @@ export declare const labelTheme: import("tailwind-variants").TVReturnType<{
2
2
  required: {
3
3
  true: string;
4
4
  };
5
- indent: {
6
- none: string;
7
- sm: string;
8
- md: string;
9
- lg: string;
10
- };
11
5
  }, undefined, "inline-flex items-center gap-1 text-sm leading-none font-medium text-foreground select-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50", {
12
6
  required: {
13
7
  true: string;
14
8
  };
15
- indent: {
16
- none: string;
17
- sm: string;
18
- md: string;
19
- lg: string;
20
- };
21
9
  }, undefined, import("tailwind-variants").TVReturnType<{
22
10
  required: {
23
11
  true: string;
24
12
  };
25
- indent: {
26
- none: string;
27
- sm: string;
28
- md: string;
29
- lg: string;
30
- };
31
13
  }, undefined, "inline-flex items-center gap-1 text-sm leading-none font-medium text-foreground select-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50", unknown, unknown, undefined>>;
32
14
  export type LabelVariants = Parameters<typeof labelTheme>[0];
@@ -0,0 +1,92 @@
1
+ export declare const numberInputTheme: import("tailwind-variants").TVReturnType<{
2
+ size: {
3
+ sm: {
4
+ input: string;
5
+ stepper: string;
6
+ };
7
+ md: {
8
+ input: string;
9
+ stepper: string;
10
+ };
11
+ lg: {
12
+ input: string;
13
+ stepper: string;
14
+ };
15
+ };
16
+ invalid: {
17
+ true: {
18
+ input: string;
19
+ };
20
+ };
21
+ /** Leaves room for the stepper so long values can't slide under it. */
22
+ withStepper: {
23
+ true: {};
24
+ };
25
+ }, {
26
+ root: string;
27
+ input: string;
28
+ /** Stacked +/- controls pinned inside the trailing edge of the field. */
29
+ stepper: string;
30
+ step: string;
31
+ }, undefined, {
32
+ size: {
33
+ sm: {
34
+ input: string;
35
+ stepper: string;
36
+ };
37
+ md: {
38
+ input: string;
39
+ stepper: string;
40
+ };
41
+ lg: {
42
+ input: string;
43
+ stepper: string;
44
+ };
45
+ };
46
+ invalid: {
47
+ true: {
48
+ input: string;
49
+ };
50
+ };
51
+ /** Leaves room for the stepper so long values can't slide under it. */
52
+ withStepper: {
53
+ true: {};
54
+ };
55
+ }, {
56
+ root: string;
57
+ input: string;
58
+ /** Stacked +/- controls pinned inside the trailing edge of the field. */
59
+ stepper: string;
60
+ step: string;
61
+ }, import("tailwind-variants").TVReturnType<{
62
+ size: {
63
+ sm: {
64
+ input: string;
65
+ stepper: string;
66
+ };
67
+ md: {
68
+ input: string;
69
+ stepper: string;
70
+ };
71
+ lg: {
72
+ input: string;
73
+ stepper: string;
74
+ };
75
+ };
76
+ invalid: {
77
+ true: {
78
+ input: string;
79
+ };
80
+ };
81
+ /** Leaves room for the stepper so long values can't slide under it. */
82
+ withStepper: {
83
+ true: {};
84
+ };
85
+ }, {
86
+ root: string;
87
+ input: string;
88
+ /** Stacked +/- controls pinned inside the trailing edge of the field. */
89
+ stepper: string;
90
+ step: string;
91
+ }, undefined, unknown, unknown, undefined>>;
92
+ export type NumberInputSlots = keyof ReturnType<typeof numberInputTheme>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "iryx-ui",
3
3
  "type": "module",
4
- "version": "0.3.0",
4
+ "version": "0.4.0",
5
5
  "description": "A Vue 3 component library built on Reka UI and Tailwind CSS v4.",
6
6
  "author": "therok1",
7
7
  "license": "MIT",