orio-ui 1.28.1 → 1.29.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
@@ -18,12 +18,12 @@ orio-ui's shipped, version-pinned agent docs. Details in
18
18
 
19
19
  ## Features
20
20
 
21
- ✨ **58 Components** - Beautiful, accessible components ready to use
21
+ ✨ **59 Components** - Beautiful, accessible components ready to use
22
22
  🎨 **Themeable** - 5 built-in accent themes with light/dark mode support
23
23
  🚀 **Auto-imported** - Works seamlessly with Nuxt's auto-import system
24
24
  📦 **Tree-shakeable** - Only bundle what you use
25
25
  🎯 **TypeScript** - Fully typed for great developer experience
26
- 🧪 **Tested** - 37 test suites for reliability
26
+ 🧪 **Tested** - 38 test suites for reliability
27
27
  📱 **Responsive** - Mobile-first design approach
28
28
  ♿ **Accessible** - ARIA-compliant components
29
29
  🌐 **i18n** - Built-in vue-i18n support with English defaults
@@ -77,7 +77,7 @@ function handleClick() {
77
77
 
78
78
  ## What's Included
79
79
 
80
- ### Components (58)
80
+ ### Components (59)
81
81
 
82
82
  #### Form Controls
83
83
 
@@ -269,7 +269,7 @@ npm run docs:dev
269
269
  orio-ui/
270
270
  ├── src/
271
271
  │ ├── runtime/
272
- │ │ ├── components/ # 58 Vue components
272
+ │ │ ├── components/ # 59 Vue components
273
273
  │ │ ├── composables/ # 15 composables
274
274
  │ │ ├── assets/css/ # Theme CSS files
275
275
  │ │ └── utils/ # Icon registry
@@ -82,6 +82,7 @@ installed version.
82
82
  - `NumberInput/Horizontal.vue` — number input variant with minus/plus buttons flanking the field and press-and-hold repeat. **Read USAGE.md first.**
83
83
  - `NumberInput/Vertical.vue` — number input variant with chevron up/down stacked on the right and press-and-hold repeat. **Read USAGE.md first.**
84
84
  - `RadioButton.vue` — single radio option wrapping ControlElement; group by sharing the same v-model. **Read USAGE.md first.**
85
+ - `SegmentedInput.vue` — fixed-length code input split into auto-advancing per-character segments for OTP / PIN entry. **Read USAGE.md first.**
85
86
  - `Selector.vue` — button-triggered listbox in a popover; supports single and multi-select with string or object options. **Read USAGE.md first.**
86
87
  - `SwitchButton.vue` — boolean on/off pill button (not a sliding switch) wrapping ControlElement; click/Enter/Space toggle. **Read USAGE.md first.**
87
88
  - `TaggableSelector.vue` — multi-select Selector that renders chosen options as tag chips in the trigger. **Read USAGE.md first.**
@@ -55,6 +55,7 @@ not edit by hand.
55
55
  - **number input horizontal, minus-plus stepper, quantity stepper** → `NumberInput/Horizontal.vue` (read USAGE.md first)
56
56
  - **number input vertical, chevron stepper, stacked-arrow numeric input** → `NumberInput/Vertical.vue` (read USAGE.md first)
57
57
  - **radio, radio button, single-choice from group** → `RadioButton.vue` (read USAGE.md first)
58
+ - **OTP input, one-time password, verification code, PIN code, segmented code boxes** → `SegmentedInput.vue` (read USAGE.md first)
58
59
  - **select, dropdown, combobox, listbox picker, single or multi-select** → `Selector.vue` (read USAGE.md first)
59
60
  - **toggle, on/off switch, pill toggle, boolean button** → `SwitchButton.vue` (read USAGE.md first)
60
61
  - **multi-select with tag chips, taggable selector, chip picker** → `TaggableSelector.vue` (read USAGE.md first)
@@ -50,6 +50,7 @@ not edit by hand.
50
50
  - **number input horizontal, minus-plus stepper, quantity stepper** → `NumberInput/Horizontal.vue` (read USAGE.md first)
51
51
  - **number input vertical, chevron stepper, stacked-arrow numeric input** → `NumberInput/Vertical.vue` (read USAGE.md first)
52
52
  - **radio, radio button, single-choice from group** → `RadioButton.vue` (read USAGE.md first)
53
+ - **OTP input, one-time password, verification code, PIN code, segmented code boxes** → `SegmentedInput.vue` (read USAGE.md first)
53
54
  - **select, dropdown, combobox, listbox picker, single or multi-select** → `Selector.vue` (read USAGE.md first)
54
55
  - **toggle, on/off switch, pill toggle, boolean button** → `SwitchButton.vue` (read USAGE.md first)
55
56
  - **multi-select with tag chips, taggable selector, chip picker** → `TaggableSelector.vue` (read USAGE.md first)
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^3.0.0 || ^4.0.0"
6
6
  },
7
- "version": "1.28.1",
7
+ "version": "1.29.0",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
@@ -26,6 +26,10 @@ invariants: true
26
26
  on the underlying `<input>`.
27
27
  - **v-model is `string`** (default `""`). For numeric input use
28
28
  `<orio-number-input>` instead.
29
+ - **`defineExpose({ input, focused })`** — `input` is the template ref to the
30
+ native `<input>`; `focused` is the **writable** `Ref<boolean>` from
31
+ `useFocus`. Reading reflects focus state; assigning `true`/`false` focuses or
32
+ blurs the element. Drive programmatic focus via `focused`, not `input.focus()`.
29
33
 
30
34
  ## Gotchas
31
35
 
@@ -14,7 +14,10 @@ type __VLS_Slots = {} & {
14
14
  } & {
15
15
  after?: (props: typeof __VLS_10) => any;
16
16
  };
17
- declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
17
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
18
+ input: Readonly<import("vue").ShallowRef<HTMLInputElement | null, HTMLInputElement | null>>;
19
+ focused: import("vue").Ref<boolean, boolean>;
20
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
18
21
  "update:modelValue": (value: string) => any;
19
22
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
20
23
  "onUpdate:modelValue"?: ((value: string) => any) | undefined;
@@ -1,4 +1,6 @@
1
1
  <script setup>
2
+ import { useTemplateRef } from "vue";
3
+ import { useFocus } from "@vueuse/core";
2
4
  const props = defineProps({
3
5
  layout: { type: String, required: false, default: "vertical" },
4
6
  appearance: { type: String, required: false },
@@ -15,7 +17,10 @@ const props = defineProps({
15
17
  name: { type: String, required: false },
16
18
  ariaLabel: { type: String, required: false }
17
19
  });
20
+ const input = useTemplateRef("input");
21
+ const { focused } = useFocus(input);
18
22
  const modelValue = defineModel({ type: String, ...{ default: "" } });
23
+ defineExpose({ input, focused });
19
24
  </script>
20
25
 
21
26
  <template>
@@ -27,6 +32,7 @@ const modelValue = defineModel({ type: String, ...{ default: "" } });
27
32
  >
28
33
  <slot name="before" />
29
34
  <input
35
+ ref="input"
30
36
  v-model="modelValue"
31
37
  type="text"
32
38
  v-bind="{ ...$attrs, ...control }"
@@ -14,7 +14,10 @@ type __VLS_Slots = {} & {
14
14
  } & {
15
15
  after?: (props: typeof __VLS_10) => any;
16
16
  };
17
- declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
17
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
18
+ input: Readonly<import("vue").ShallowRef<HTMLInputElement | null, HTMLInputElement | null>>;
19
+ focused: import("vue").Ref<boolean, boolean>;
20
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
18
21
  "update:modelValue": (value: string) => any;
19
22
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
20
23
  "onUpdate:modelValue"?: ((value: string) => any) | undefined;
@@ -40,6 +40,10 @@ invariants: true
40
40
  prop bag.
41
41
  - **`$attrs` is spread before `control`** on the inner `<input>`, same as
42
42
  Input.
43
+ - **`defineExpose({ input, focused })`** — `input` is the template ref to the
44
+ native `<input>`; `focused` is the **writable** `Ref<boolean>` from
45
+ `useFocus`. Reading reflects focus state; assigning `true`/`false` focuses or
46
+ blurs the element. Drive programmatic focus via `focused`, not `input.focus()`.
43
47
 
44
48
  ## Gotchas
45
49
 
@@ -11,7 +11,7 @@ type __VLS_Props = NumberInputProps;
11
11
  declare function increase(): void;
12
12
  declare function decrease(): void;
13
13
  type __VLS_ModelProps = {
14
- modelValue?: number;
14
+ modelValue?: number | null;
15
15
  };
16
16
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
17
17
  declare var __VLS_8: {
@@ -23,10 +23,13 @@ declare var __VLS_8: {
23
23
  type __VLS_Slots = {} & {
24
24
  controls?: (props: typeof __VLS_8) => any;
25
25
  };
26
- declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
27
- "update:modelValue": (value: number) => any;
26
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
27
+ input: Readonly<import("vue").ShallowRef<HTMLInputElement | null, HTMLInputElement | null>>;
28
+ focused: import("vue").Ref<boolean, boolean>;
29
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
30
+ "update:modelValue": (value: number | null) => any;
28
31
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
29
- "onUpdate:modelValue"?: ((value: number) => any) | undefined;
32
+ "onUpdate:modelValue"?: ((value: number | null) => any) | undefined;
30
33
  }>, {
31
34
  layout: InputLayout;
32
35
  step: number;
@@ -1,5 +1,6 @@
1
1
  <script setup>
2
- import { computed, toRefs } from "vue";
2
+ import { computed, toRefs, useTemplateRef } from "vue";
3
+ import { useFocus } from "@vueuse/core";
3
4
  const props = defineProps({
4
5
  layout: { type: String, required: false, default: "vertical" },
5
6
  min: { type: Number, required: false, default: void 0 },
@@ -21,9 +22,11 @@ const props = defineProps({
21
22
  ariaLabel: { type: String, required: false }
22
23
  });
23
24
  const { min, max, step, decimalPlaces } = toRefs(props);
24
- const modelValue = defineModel({ type: Number, ...{ default: 0 } });
25
+ const modelValue = defineModel({ type: [Number, null], ...{ default: 0 } });
26
+ const input = useTemplateRef("input");
27
+ const { focused } = useFocus(input);
25
28
  function setValidatedValue(value) {
26
- let finalValue = value;
29
+ let finalValue = value ?? 0;
27
30
  if (Number.isFinite(max.value) && finalValue > max.value) {
28
31
  finalValue = max.value;
29
32
  }
@@ -37,16 +40,16 @@ function onBlur() {
37
40
  setValidatedValue(modelValue.value);
38
41
  }
39
42
  function increase() {
40
- setValidatedValue(modelValue.value + step.value);
43
+ setValidatedValue((modelValue.value ?? 0) + step.value);
41
44
  }
42
45
  function decrease() {
43
- setValidatedValue(modelValue.value - step.value);
46
+ setValidatedValue((modelValue.value ?? 0) - step.value);
44
47
  }
45
48
  const isAtMax = computed(
46
- () => Number.isFinite(max.value) && modelValue.value >= max.value
49
+ () => Number.isFinite(max.value) && (modelValue.value ?? 0) >= max.value
47
50
  );
48
51
  const isAtMin = computed(
49
- () => Number.isFinite(min.value) && modelValue.value <= min.value
52
+ () => Number.isFinite(min.value) && (modelValue.value ?? 0) <= min.value
50
53
  );
51
54
  const controlProps = computed(() => {
52
55
  const {
@@ -64,6 +67,7 @@ const slotExpose = computed(() => ({
64
67
  isAtMax: isAtMax.value,
65
68
  isAtMin: isAtMin.value
66
69
  }));
70
+ defineExpose({ input, focused });
67
71
  </script>
68
72
 
69
73
  <template>
@@ -76,6 +80,7 @@ const slotExpose = computed(() => ({
76
80
  <div class="wrapper">
77
81
  <input
78
82
  v-bind="{ ...$attrs, ...control }"
83
+ ref="input"
79
84
  v-model="modelValue"
80
85
  type="number"
81
86
  class="number-input"
@@ -11,7 +11,7 @@ type __VLS_Props = NumberInputProps;
11
11
  declare function increase(): void;
12
12
  declare function decrease(): void;
13
13
  type __VLS_ModelProps = {
14
- modelValue?: number;
14
+ modelValue?: number | null;
15
15
  };
16
16
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
17
17
  declare var __VLS_8: {
@@ -23,10 +23,13 @@ declare var __VLS_8: {
23
23
  type __VLS_Slots = {} & {
24
24
  controls?: (props: typeof __VLS_8) => any;
25
25
  };
26
- declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
27
- "update:modelValue": (value: number) => any;
26
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
27
+ input: Readonly<import("vue").ShallowRef<HTMLInputElement | null, HTMLInputElement | null>>;
28
+ focused: import("vue").Ref<boolean, boolean>;
29
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
30
+ "update:modelValue": (value: number | null) => any;
28
31
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
29
- "onUpdate:modelValue"?: ((value: number) => any) | undefined;
32
+ "onUpdate:modelValue"?: ((value: number | null) => any) | undefined;
30
33
  }>, {
31
34
  layout: InputLayout;
32
35
  step: number;
@@ -0,0 +1,67 @@
1
+ ---
2
+ kind: component
3
+ category: Form inputs
4
+ purpose: OTP input, one-time password, verification code, PIN code, segmented code boxes
5
+ short: fixed-length code input split into auto-advancing per-character segments for OTP / PIN entry
6
+ invariants: true
7
+ ---
8
+
9
+ # SegmentedInput — agent-only invariants
10
+
11
+ `<orio-segmented-input>` renders `segments` × `<orio-input>` boxes and joins
12
+ them into a single v-model string. Built for OTP / verification-code entry.
13
+
14
+ ## Invariants
15
+
16
+ - **Does NOT extend `ControlProps`** — unlike other form inputs there is no
17
+ `label`, `layout`, `disabled`, or ControlElement wrapper. Add your own
18
+ label / a11y wrapper in the consumer.
19
+ - **v-model is the plain concatenation** of all segment values
20
+ (`string | number`, default `""`). External model writes re-split across
21
+ segments (`segmentSize` characters each).
22
+ - **Sparse fills collapse.** Segments `["1", "", "3"]` join to `"13"`, which
23
+ immediately re-splits as `["1", "3", ""]` — characters shift left past
24
+ empty segments. The model can never hold positional gaps.
25
+ - **Keyboard handling is a window-level `onKeyDown`** that bails unless one
26
+ of its own segments is focused. Auto-advance happens on keydown when the
27
+ focused segment is already full (the key lands in the next segment);
28
+ Backspace on an empty segment moves focus back.
29
+ - **`type="number"`** (default) `preventDefault`s non-digit printable keys
30
+ and sets `inputmode="numeric"` on every segment. Modifier shortcuts
31
+ (Cmd/Ctrl/Alt) and navigation keys pass through. `type="string"` accepts
32
+ anything.
33
+ - **`start` / `end` events** fire when focus would step before the first
34
+ segment (Backspace) or past the last one (typed into the final full
35
+ segment). Use `end` for auto-submit.
36
+ - The first segment has `autocomplete="one-time-code"`; the rest are
37
+ `autocomplete="off"`.
38
+ - **Paste is intercepted** (`@paste.prevent` on the wrapper): the pasted
39
+ text replaces `modelValue` wholesale — digits-only filtered for
40
+ `type="number"`, trimmed for `type="string"`, truncated to
41
+ `segments × segmentSize`. A paste that fills every segment emits `end`.
42
+
43
+ ## Gotchas
44
+
45
+ - **Paste replaces the whole value**, regardless of which segment is
46
+ focused — it does not insert at the focused position.
47
+ - **SMS autofill** (`one-time-code`) inserts via the input value setter, not
48
+ a paste event — it still lands in segment 0 and is truncated by
49
+ `maxlength`.
50
+ - `segments` / `segmentSize` accept `number | string` (loose HTML-attr
51
+ usage) and are `Number()`-coerced internally.
52
+ - Programmatic focus of a segment goes through the exposed `focused` ref of
53
+ `Input.vue` (`inputComponent.focused = true`), not `element.focus()`.
54
+ - Multiple instances on one page are safe — each window listener no-ops
55
+ unless one of its own segments is focused.
56
+
57
+ ## Quick reference
58
+
59
+ ```vue
60
+ <orio-segmented-input
61
+ v-model="code"
62
+ :segments="6"
63
+ :segment-size="1"
64
+ type="number"
65
+ @end="submitCode()"
66
+ />
67
+ ```
@@ -0,0 +1,22 @@
1
+ interface Props {
2
+ segments?: number | string;
3
+ segmentSize?: number | string;
4
+ type?: "number" | "string";
5
+ }
6
+ type __VLS_Props = Props;
7
+ type __VLS_ModelProps = {
8
+ modelValue?: string | number;
9
+ };
10
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
11
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
+ "update:modelValue": (value: string | number) => any;
13
+ } & {
14
+ end: () => any;
15
+ start: () => any;
16
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
17
+ onEnd?: (() => any) | undefined;
18
+ onStart?: (() => any) | undefined;
19
+ "onUpdate:modelValue"?: ((value: string | number) => any) | undefined;
20
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ declare const _default: typeof __VLS_export;
22
+ export default _default;
@@ -0,0 +1,114 @@
1
+ <script setup>
2
+ import { ref, computed, watch, watchEffect } from "vue";
3
+ import Input from "./Input.vue";
4
+ import { useTemplateRef } from "vue";
5
+ import { onKeyDown } from "@vueuse/core";
6
+ const { segments = 6, segmentSize = 1, type = "number" } = defineProps({
7
+ segments: { type: [Number, String], required: false },
8
+ segmentSize: { type: [Number, String], required: false },
9
+ type: { type: String, required: false }
10
+ });
11
+ const emit = defineEmits(["start", "end"]);
12
+ const modelValue = defineModel({ type: [String, Number], ...{ default: "" } });
13
+ function applyModel(index) {
14
+ return String(modelValue.value).slice(
15
+ index * Number(segmentSize),
16
+ index * Number(segmentSize) + Number(segmentSize)
17
+ );
18
+ }
19
+ function setupValue() {
20
+ return Array.from(
21
+ { length: Number(segments) },
22
+ (_, index) => applyModel(index)
23
+ );
24
+ }
25
+ const inputComponents = useTemplateRef("inputComponents");
26
+ const inputComponentsModel = ref(setupValue());
27
+ function focusSegment(index) {
28
+ const target = inputComponents.value?.[index];
29
+ if (target) target.focused = true;
30
+ }
31
+ const focusState = computed(() => {
32
+ const currentIndex = inputComponents.value?.findIndex(
33
+ (inputComponent) => inputComponent?.focused
34
+ );
35
+ if (currentIndex === void 0 || currentIndex === -1)
36
+ return { currentIndex: void 0, focusedElement: null };
37
+ const focusedElement = inputComponents.value?.[currentIndex];
38
+ return { currentIndex, focusedElement };
39
+ });
40
+ function focusMove(delta) {
41
+ if (focusState.value.currentIndex === void 0) return;
42
+ let newIndex = focusState.value.currentIndex + delta;
43
+ const maxIndex = inputComponents.value?.length ?? 0;
44
+ if (newIndex >= maxIndex - 1) {
45
+ emit("end");
46
+ newIndex = maxIndex - 1;
47
+ }
48
+ if (newIndex <= 0) {
49
+ emit("start");
50
+ newIndex = 0;
51
+ }
52
+ focusSegment(newIndex);
53
+ }
54
+ onKeyDown(true, (event) => {
55
+ const { currentIndex } = focusState.value;
56
+ if (currentIndex === void 0) return;
57
+ if (event.key === "Backspace") {
58
+ if (inputComponentsModel.value[currentIndex]?.length === 0) focusMove(-1);
59
+ return;
60
+ }
61
+ if (event.metaKey || event.ctrlKey || event.altKey) return;
62
+ if (event.key.length > 1) return;
63
+ if (type === "number" && !/^\d$/.test(event.key)) {
64
+ event.preventDefault();
65
+ return;
66
+ }
67
+ const currentValue = inputComponentsModel.value[currentIndex] ?? "";
68
+ if (currentValue.length >= Number(segmentSize)) focusMove(1);
69
+ });
70
+ function handlePaste(event) {
71
+ const pastedText = event.clipboardData?.getData("text") ?? "";
72
+ const sanitizedText = type === "number" ? pastedText.replace(/\D/g, "") : pastedText.trim();
73
+ if (!sanitizedText) return;
74
+ const capacity = Number(segments) * Number(segmentSize);
75
+ modelValue.value = sanitizedText.slice(0, capacity);
76
+ if (sanitizedText.length >= capacity) emit("end");
77
+ }
78
+ watch(
79
+ () => inputComponentsModel.value.join(""),
80
+ (joinedValue) => {
81
+ modelValue.value = joinedValue;
82
+ }
83
+ );
84
+ watchEffect(() => {
85
+ inputComponentsModel.value = setupValue();
86
+ });
87
+ </script>
88
+
89
+ <template>
90
+ <div class="segmented-input" @paste.prevent="handlePaste">
91
+ <Input
92
+ v-for="(segment, index) in inputComponentsModel"
93
+ :key="index"
94
+ ref="inputComponents"
95
+ v-model="inputComponentsModel[index]"
96
+ :maxlength="segmentSize"
97
+ :inputmode="type === 'number' ? 'numeric' : void 0"
98
+ :autocomplete="index === 0 ? 'one-time-code' : 'off'"
99
+ />
100
+ </div>
101
+ </template>
102
+
103
+ <style scoped>
104
+ .segmented-input {
105
+ display: flex;
106
+ }
107
+ .segmented-input > div {
108
+ flex: 1 1 0;
109
+ min-width: 0;
110
+ }
111
+ .segmented-input :deep(input) {
112
+ text-align: center;
113
+ }
114
+ </style>
@@ -0,0 +1,22 @@
1
+ interface Props {
2
+ segments?: number | string;
3
+ segmentSize?: number | string;
4
+ type?: "number" | "string";
5
+ }
6
+ type __VLS_Props = Props;
7
+ type __VLS_ModelProps = {
8
+ modelValue?: string | number;
9
+ };
10
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
11
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
+ "update:modelValue": (value: string | number) => any;
13
+ } & {
14
+ end: () => any;
15
+ start: () => any;
16
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
17
+ onEnd?: (() => any) | undefined;
18
+ onStart?: (() => any) | undefined;
19
+ "onUpdate:modelValue"?: ((value: string | number) => any) | undefined;
20
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ declare const _default: typeof __VLS_export;
22
+ export default _default;
@@ -1,4 +1,4 @@
1
- import { Ref } from "vue";
1
+ import { type Ref } from "vue";
2
2
  /**
3
3
  * Syncs a reactive object's keys to/from URL query params.
4
4
  *
@@ -3,6 +3,7 @@ export { default as Button } from "./components/Button.vue.js";
3
3
  export { default as Form, type FormProps } from "./components/Form.vue.js";
4
4
  export { default as NavButton } from "./components/NavButton.vue.js";
5
5
  export { default as Input } from "./components/Input.vue.js";
6
+ export { default as SegmentedInput } from "./components/SegmentedInput.vue.js";
6
7
  export { default as NumberInput } from "./components/NumberInput/index.vue.js";
7
8
  export { default as NumberInputVertical } from "./components/NumberInput/Vertical.vue.js";
8
9
  export { default as NumberInputHorizontal } from "./components/NumberInput/Horizontal.vue.js";
@@ -3,6 +3,7 @@ export { default as Button } from "./components/Button.vue";
3
3
  export { default as Form } from "./components/Form.vue";
4
4
  export { default as NavButton } from "./components/NavButton.vue";
5
5
  export { default as Input } from "./components/Input.vue";
6
+ export { default as SegmentedInput } from "./components/SegmentedInput.vue";
6
7
  export { default as NumberInput } from "./components/NumberInput/index.vue";
7
8
  export { default as NumberInputVertical } from "./components/NumberInput/Vertical.vue";
8
9
  export { default as NumberInputHorizontal } from "./components/NumberInput/Horizontal.vue";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orio-ui",
3
- "version": "1.28.1",
3
+ "version": "1.29.0",
4
4
  "description": "Modern Nuxt component library with theme support",
5
5
  "type": "module",
6
6
  "main": "./dist/module.mjs",