orio-ui 1.24.0 → 1.28.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 +78 -3
- package/bin/orio-ui.mjs +72 -0
- package/dist/agents/ROUTING.md +140 -0
- package/dist/agents/component-finder.md +142 -0
- package/dist/agents/component-worker.md +152 -0
- package/dist/agents/snippet.md +6 -0
- package/dist/module.json +1 -1
- package/dist/runtime/components/AnimatedContainer.USAGE.md +79 -0
- package/dist/runtime/components/Badge.USAGE.md +75 -0
- package/dist/runtime/components/Banner.USAGE.md +52 -0
- package/dist/runtime/components/Button.USAGE.md +78 -0
- package/dist/runtime/components/Button.d.vue.ts +3 -2
- package/dist/runtime/components/Button.vue +19 -11
- package/dist/runtime/components/Button.vue.d.ts +3 -2
- package/dist/runtime/components/Calendar.USAGE.md +59 -0
- package/dist/runtime/components/Calendar.vue +254 -87
- package/dist/runtime/components/Canvas/USAGE.md +73 -0
- package/dist/runtime/components/CheckBox.USAGE.md +63 -0
- package/dist/runtime/components/CheckBox.vue +9 -3
- package/dist/runtime/components/CheckboxGroup.USAGE.md +95 -0
- package/dist/runtime/components/CheckboxGroup.vue +7 -1
- package/dist/runtime/components/ControlElement.USAGE.md +77 -0
- package/dist/runtime/components/ControlElement.d.vue.ts +42 -27
- package/dist/runtime/components/ControlElement.vue +28 -9
- package/dist/runtime/components/ControlElement.vue.d.ts +42 -27
- package/dist/runtime/components/DashedContainer.USAGE.md +65 -0
- package/dist/runtime/components/EmptyState.USAGE.md +65 -0
- package/dist/runtime/components/Form.USAGE.md +102 -0
- package/dist/runtime/components/Icon.USAGE.md +61 -0
- package/dist/runtime/components/Input.USAGE.md +57 -0
- package/dist/runtime/components/Input.vue +13 -3
- package/dist/runtime/components/ListItem.USAGE.md +84 -0
- package/dist/runtime/components/LoadingSpinner.USAGE.md +50 -0
- package/dist/runtime/components/LocaleSwitcher.USAGE.md +73 -0
- package/dist/runtime/components/Modal.USAGE.md +72 -0
- package/dist/runtime/components/NavButton.USAGE.md +80 -0
- package/dist/runtime/components/NavButton.d.vue.ts +0 -1
- package/dist/runtime/components/NavButton.vue +9 -5
- package/dist/runtime/components/NavButton.vue.d.ts +0 -1
- package/dist/runtime/components/NumberInput/Horizontal.USAGE.md +61 -0
- package/dist/runtime/components/NumberInput/Horizontal.vue +7 -2
- package/dist/runtime/components/NumberInput/USAGE.md +74 -0
- package/dist/runtime/components/NumberInput/Vertical.USAGE.md +55 -0
- package/dist/runtime/components/NumberInput/Vertical.vue +7 -2
- package/dist/runtime/components/NumberInput/index.d.vue.ts +0 -2
- package/dist/runtime/components/NumberInput/index.vue +9 -7
- package/dist/runtime/components/NumberInput/index.vue.d.ts +0 -2
- package/dist/runtime/components/Popover.USAGE.md +103 -0
- package/dist/runtime/components/RadioButton.USAGE.md +72 -0
- package/dist/runtime/components/RadioButton.d.vue.ts +0 -2
- package/dist/runtime/components/RadioButton.vue +9 -4
- package/dist/runtime/components/RadioButton.vue.d.ts +0 -2
- package/dist/runtime/components/Selector.USAGE.md +131 -0
- package/dist/runtime/components/Selector.d.vue.ts +1 -0
- package/dist/runtime/components/Selector.vue +10 -4
- package/dist/runtime/components/Selector.vue.d.ts +1 -0
- package/dist/runtime/components/SwitchButton.USAGE.md +62 -0
- package/dist/runtime/components/SwitchButton.d.vue.ts +1 -4
- package/dist/runtime/components/SwitchButton.vue +10 -7
- package/dist/runtime/components/SwitchButton.vue.d.ts +1 -4
- package/dist/runtime/components/Tag.USAGE.md +51 -0
- package/dist/runtime/components/TaggableSelector.USAGE.md +73 -0
- package/dist/runtime/components/TaggableSelector.vue +7 -1
- package/dist/runtime/components/Textarea.USAGE.md +72 -0
- package/dist/runtime/components/Textarea.vue +13 -3
- package/dist/runtime/components/Tooltip.USAGE.md +84 -0
- package/dist/runtime/components/ZoomableContainer.USAGE.md +108 -0
- package/dist/runtime/components/date/Picker.USAGE.md +52 -0
- package/dist/runtime/components/date/Picker.vue +7 -1
- package/dist/runtime/components/date/PickerTrigger.USAGE.md +65 -0
- package/dist/runtime/components/date/PickerTrigger.vue +9 -3
- package/dist/runtime/components/date/RangePicker.USAGE.md +97 -0
- package/dist/runtime/components/date/RangePicker.vue +7 -1
- package/dist/runtime/components/gallery/Carousel.USAGE.md +98 -0
- package/dist/runtime/components/gallery/CarouselPreview.USAGE.md +51 -0
- package/dist/runtime/components/upload/USAGE.md +91 -0
- package/dist/runtime/components/view/Dates.USAGE.md +67 -0
- package/dist/runtime/components/view/KeyBinds.USAGE.md +58 -0
- package/dist/runtime/components/view/Separator.USAGE.md +57 -0
- package/dist/runtime/components/view/Text.USAGE.md +68 -0
- package/dist/runtime/composables/useApi.USAGE.md +64 -0
- package/dist/runtime/composables/useControlSize.USAGE.md +73 -0
- package/dist/runtime/composables/useDecimalFormatter.USAGE.md +72 -0
- package/dist/runtime/composables/useFilter.USAGE.md +120 -0
- package/dist/runtime/composables/useFilter.d.ts +91 -0
- package/dist/runtime/composables/useFilter.js +111 -0
- package/dist/runtime/composables/useFuzzySearch.USAGE.md +68 -0
- package/dist/runtime/composables/useInertia.USAGE.md +80 -0
- package/dist/runtime/composables/useListKeyboard.USAGE.md +97 -0
- package/dist/runtime/composables/useModal.USAGE.md +82 -0
- package/dist/runtime/composables/usePinchZoom.USAGE.md +95 -0
- package/dist/runtime/composables/usePressAndHold.USAGE.md +70 -0
- package/dist/runtime/composables/useRovingGrid.USAGE.md +106 -0
- package/dist/runtime/composables/useRovingGrid.d.ts +35 -0
- package/dist/runtime/composables/useRovingGrid.js +115 -0
- package/dist/runtime/composables/useSound.USAGE.md +74 -0
- package/dist/runtime/composables/useTheme.USAGE.md +76 -0
- package/dist/runtime/composables/useUrlSync.USAGE.md +91 -0
- package/dist/runtime/composables/useValidation.USAGE.md +100 -0
- package/dist/runtime/i18n/en.json +4 -1
- package/dist/runtime/i18n/uk.json +4 -1
- package/package.json +12 -2
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
kind: component
|
|
3
|
+
category: Layout & containers
|
|
4
|
+
purpose: animation wrapper, fade/slide a slot, animated list, mount-stagger layout
|
|
5
|
+
short: flex container that fade-slides its direct children up on mount and exposes a sound `play` callback
|
|
6
|
+
invariants: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# AnimatedContainer — agent-only invariants
|
|
10
|
+
|
|
11
|
+
`<orio-animated-container>` is a flex layout that runs a fade-in-up CSS
|
|
12
|
+
animation on every direct child when it mounts. It is **not** a Vue
|
|
13
|
+
`<Transition>` — there is no leave animation and reactive state changes do
|
|
14
|
+
not retrigger it.
|
|
15
|
+
|
|
16
|
+
## Invariants
|
|
17
|
+
|
|
18
|
+
- **Animation fires on mount only.** The `containerFadeInUp` keyframe is a
|
|
19
|
+
plain CSS animation on `.animated-container > *`. To replay, change
|
|
20
|
+
`:key` on the container (or on the child). Re-rendering reactive content
|
|
21
|
+
inside the slot does **not** restart the animation.
|
|
22
|
+
- **Only direct children animate.** The selector is `> *`. Wrapping children
|
|
23
|
+
in an extra `<div>` moves the animation up to the wrapper. Nested deep
|
|
24
|
+
trees do not animate per-node.
|
|
25
|
+
- **Layout is opinionated.** The container is `display: flex; flex-wrap:
|
|
26
|
+
wrap; justify-content: center; gap: 1rem; padding-inline: 1rem;`. Treat it
|
|
27
|
+
as a layout primitive, not a transparent wrapper.
|
|
28
|
+
- **`direction` toggles flex-direction _and_ justification.** `"row"`
|
|
29
|
+
(default) → wrap + centered. `"column"` → `flex-direction: column` +
|
|
30
|
+
`justify-content: flex-start`.
|
|
31
|
+
- **`play` slot prop is `useSound().play`.** The default slot exposes
|
|
32
|
+
`{ play }`. Wire it to `@mouseenter` / `@click` on children for hover or
|
|
33
|
+
tap feedback. There is no prop to disable or swap the sound — it is
|
|
34
|
+
global `useSound`.
|
|
35
|
+
|
|
36
|
+
## Gotchas
|
|
37
|
+
|
|
38
|
+
- **No leave animation.** Items removed from the slot disappear instantly.
|
|
39
|
+
If you need exit animation, wrap each item in `<Transition>` or use a
|
|
40
|
+
different primitive.
|
|
41
|
+
- **Newly inserted children animate independently.** When the slot's child
|
|
42
|
+
list grows (v-for over a reactive array), each new node animates on its
|
|
43
|
+
own mount — there is no list-coordinated stagger.
|
|
44
|
+
- **Built-in horizontal padding bleeds.** `padding-inline: 1rem` is on the
|
|
45
|
+
container. If the consumer wraps it in a tight column, the inner content
|
|
46
|
+
starts 1rem in. Override with `:deep(.animated-container)` or pad the
|
|
47
|
+
parent.
|
|
48
|
+
- **`direction="column"` does not stretch children.** They still wrap by
|
|
49
|
+
default (`flex-wrap: wrap` is unchanged). Children narrower than the
|
|
50
|
+
container will not fill the row.
|
|
51
|
+
|
|
52
|
+
## Quick reference
|
|
53
|
+
|
|
54
|
+
```vue
|
|
55
|
+
<script setup lang="ts">
|
|
56
|
+
import { ref } from "vue";
|
|
57
|
+
|
|
58
|
+
const animationKey = ref(0);
|
|
59
|
+
function replay() {
|
|
60
|
+
animationKey.value += 1;
|
|
61
|
+
}
|
|
62
|
+
</script>
|
|
63
|
+
|
|
64
|
+
<template>
|
|
65
|
+
<orio-button @click="replay">Replay</orio-button>
|
|
66
|
+
|
|
67
|
+
<orio-animated-container :key="animationKey" direction="column" v-slot="{ play }">
|
|
68
|
+
<div v-for="item in items" :key="item.id" @mouseenter="play">
|
|
69
|
+
{{ item.label }}
|
|
70
|
+
</div>
|
|
71
|
+
</orio-animated-container>
|
|
72
|
+
</template>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Related
|
|
76
|
+
|
|
77
|
+
- `useSound` composable — the source of the `play` callback. See
|
|
78
|
+
`docs/composables/use-sound.md`.
|
|
79
|
+
- Public API reference: `docs/components/animated-container.md`.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
kind: component
|
|
3
|
+
category: Buttons & indicators
|
|
4
|
+
purpose: badge, small status pill, notification dot, count indicator, corner badge
|
|
5
|
+
short: small status pill or dot indicator; optionally positioned in the top-right corner of a wrapped element
|
|
6
|
+
invariants: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Badge — agent-only invariants
|
|
10
|
+
|
|
11
|
+
`<orio-badge>` renders one of two shapes:
|
|
12
|
+
- A standalone inline status pill / dot.
|
|
13
|
+
- A **positioned** badge anchored to the top-right corner of an element
|
|
14
|
+
passed via the `#wrapping` slot (typical notification-on-icon pattern).
|
|
15
|
+
|
|
16
|
+
## Invariants
|
|
17
|
+
|
|
18
|
+
- **`#wrapping` slot toggles positioning mode.** When provided, the badge
|
|
19
|
+
is rendered absolutely at `top: 15%; right: 15%; transform: translate(50%, -50%)`
|
|
20
|
+
on top of the wrapped element. Without `#wrapping`, the badge is plain
|
|
21
|
+
inline.
|
|
22
|
+
- **Default slot determines dot vs text mode.** Empty default slot → dot
|
|
23
|
+
badge (0.5rem circle, no padding). Any content → text/number badge.
|
|
24
|
+
- **`variant`**: `"primary"` (default), `"danger"`, `"alert"`, `"grey"`.
|
|
25
|
+
Maps to accent / danger / alert / surface color tokens.
|
|
26
|
+
- **`pill` prop**: switches the border-radius to pill shape; ignored when
|
|
27
|
+
in dot mode.
|
|
28
|
+
- **`hidden` prop**: gates the badge render via `v-if`. The wrapped slot
|
|
29
|
+
still renders when in wrapping mode — only the indicator hides.
|
|
30
|
+
- **No `count` prop.** Use the default slot for the number: `<orio-badge>3</orio-badge>`.
|
|
31
|
+
|
|
32
|
+
## Gotchas
|
|
33
|
+
|
|
34
|
+
- **No automatic "99+" cap.** Long content (e.g. `1234`) renders fully,
|
|
35
|
+
pushing the corner badge wider. Cap in the consumer.
|
|
36
|
+
- **Positioned badge offsets are percentages of the wrapping element.**
|
|
37
|
+
Tiny wrapped icons may have the badge clip outside the wrapper. The
|
|
38
|
+
wrapper is `position: relative; display: inline-flex` — `overflow: visible`
|
|
39
|
+
is implicit, but parent overflow may clip it.
|
|
40
|
+
- **No interactive behavior.** Click does not bubble specially; it's a
|
|
41
|
+
`<span>`. For removable chips, use `<orio-tag>` instead.
|
|
42
|
+
|
|
43
|
+
## Quick reference — corner badge on an icon
|
|
44
|
+
|
|
45
|
+
```vue
|
|
46
|
+
<template>
|
|
47
|
+
<orio-badge variant="danger">
|
|
48
|
+
<template #wrapping>
|
|
49
|
+
<orio-button icon="bell" variant="subdued" />
|
|
50
|
+
</template>
|
|
51
|
+
{{ unreadCount }}
|
|
52
|
+
</orio-badge>
|
|
53
|
+
|
|
54
|
+
<orio-badge variant="alert" :hidden="!hasUpdates">
|
|
55
|
+
<template #wrapping>
|
|
56
|
+
<orio-icon name="refresh" />
|
|
57
|
+
</template>
|
|
58
|
+
</orio-badge>
|
|
59
|
+
</template>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Quick reference — inline status pill
|
|
63
|
+
|
|
64
|
+
```vue
|
|
65
|
+
<template>
|
|
66
|
+
<orio-badge variant="grey" pill>{{ $t("status.draft") }}</orio-badge>
|
|
67
|
+
<orio-badge variant="primary">{{ $t("status.live") }}</orio-badge>
|
|
68
|
+
</template>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Related
|
|
72
|
+
|
|
73
|
+
- `<orio-tag>` — chip with text and optional `id` / variant for filters
|
|
74
|
+
and selections.
|
|
75
|
+
- Public API reference: `docs/components/badge.md`.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
kind: component
|
|
3
|
+
category: Buttons & indicators
|
|
4
|
+
purpose: banner, page-level notice, alert strip, inline notification, info bar
|
|
5
|
+
short: page-level notice strip with danger/alert/success/info variants; default slot for content
|
|
6
|
+
invariants: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Banner — agent-only invariants
|
|
10
|
+
|
|
11
|
+
`<orio-banner>` is a plain styled `<div>` for page-level notices. No icon,
|
|
12
|
+
no close button, no auto-dismiss — bring your own.
|
|
13
|
+
|
|
14
|
+
## Invariants
|
|
15
|
+
|
|
16
|
+
- **`variant`**: `"info"` (default), `"success"`, `"alert"`, `"danger"`.
|
|
17
|
+
Each maps to a soft-background + matching border color from the
|
|
18
|
+
project's color tokens.
|
|
19
|
+
- **Default slot is the entire body.** Text, links, action buttons —
|
|
20
|
+
whatever fits the layout.
|
|
21
|
+
- **Padding (`0.75rem 1rem`) and border-radius (`--border-radius-sm`)
|
|
22
|
+
are fixed.** No size variants.
|
|
23
|
+
|
|
24
|
+
## Gotchas
|
|
25
|
+
|
|
26
|
+
- **No semantic role / ARIA live region.** The `<div>` has no
|
|
27
|
+
`role="alert"` or `role="status"`. For screen-reader-announced
|
|
28
|
+
notices, add `role="alert"` (urgent) or `role="status"` (polite) via
|
|
29
|
+
`$attrs`.
|
|
30
|
+
- **No close button.** Pair with `v-if` on the consumer side for
|
|
31
|
+
dismissable banners.
|
|
32
|
+
- **No icon prop.** Render `<orio-icon>` inside the slot if needed —
|
|
33
|
+
the banner does not auto-prepend a variant-matching glyph.
|
|
34
|
+
|
|
35
|
+
## Quick reference
|
|
36
|
+
|
|
37
|
+
```vue
|
|
38
|
+
<template>
|
|
39
|
+
<orio-banner variant="alert" role="alert" v-if="paymentFailed">
|
|
40
|
+
<strong>{{ $t("billing.failed.title") }}</strong>
|
|
41
|
+
<orio-button variant="subdued" @click="retry">
|
|
42
|
+
{{ $t("billing.failed.retry") }}
|
|
43
|
+
</orio-button>
|
|
44
|
+
</orio-banner>
|
|
45
|
+
</template>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Related
|
|
49
|
+
|
|
50
|
+
- `<orio-empty-state>` — for empty-list placeholders.
|
|
51
|
+
- `<orio-tooltip>` — for transient hover hints.
|
|
52
|
+
- Public API reference: `docs/components/banner.md`.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
kind: component
|
|
3
|
+
category: Buttons & indicators
|
|
4
|
+
purpose: button, primary action, CTA, icon button, action button
|
|
5
|
+
short: primary action button with variants, loading, icon slots, and auto icon-only sizing
|
|
6
|
+
invariants: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Button — agent-only invariants
|
|
10
|
+
|
|
11
|
+
`<orio-button>` is the primary action button. Wraps `<orio-control-element>`
|
|
12
|
+
so it can carry a label/error like other form controls, but it is most
|
|
13
|
+
often used standalone.
|
|
14
|
+
|
|
15
|
+
## Invariants
|
|
16
|
+
|
|
17
|
+
- **`variant`**: `"primary"` (default), `"secondary"`, `"subdued"`. Primary
|
|
18
|
+
is filled; secondary is outline; subdued is bare text. All use the
|
|
19
|
+
global `gradient-hover` class for the hover treatment.
|
|
20
|
+
- **`icon` prop OR `#icon` slot**: pass an icon name (registered in
|
|
21
|
+
`utils/iconRegistry`) OR slot in arbitrary content before the label.
|
|
22
|
+
Slot wins.
|
|
23
|
+
- **`#icon-right` slot**: trailing icon, rendered after the default slot.
|
|
24
|
+
- **`loading` prop**: renders `<orio-loading-spinner>` in place of all
|
|
25
|
+
slot content (icon, label, icon-right are all hidden). Clicks and
|
|
26
|
+
mousedown are blocked while loading.
|
|
27
|
+
- **Icon-only mode is auto-detected.** When an icon is present and the
|
|
28
|
+
default slot is empty, `.icon-only` is applied → `aspect-ratio: 1`,
|
|
29
|
+
`line-height: 0`. No need to pass a prop.
|
|
30
|
+
- **`disabled` blocks `click` and `mousedown` emits.** `mouseup` and
|
|
31
|
+
`mouseleave` always fire (so press-and-hold callers can release
|
|
32
|
+
state).
|
|
33
|
+
- **Emits**: `click`, `mousedown`, `mouseup`, `mouseleave`. Only `click`
|
|
34
|
+
and `mousedown` honor the loading/disabled gates.
|
|
35
|
+
- **Wraps ControlElement** — supports `label`, `error`, `size`, `layout`,
|
|
36
|
+
etc. The control bag is spread on the inner `<button>` along with
|
|
37
|
+
`$attrs`.
|
|
38
|
+
|
|
39
|
+
## Gotchas
|
|
40
|
+
|
|
41
|
+
- **`$attrs` are duplicated.** Because ControlElement does **not** set
|
|
42
|
+
`inheritAttrs: false` and Button also spreads `$attrs` on the inner
|
|
43
|
+
`<button>`, an attr like `data-test="x"` may appear on both the
|
|
44
|
+
wrapper `<div>` (from ControlElement's root) and the inner `<button>`.
|
|
45
|
+
For attrs that must be unique (e.g. `data-key` for list keying,
|
|
46
|
+
`tabindex` override), bind a plain native `<button>` instead of
|
|
47
|
+
`<orio-button>`.
|
|
48
|
+
- **`type` defaults to `submit`** (native default). Inside an
|
|
49
|
+
`<orio-form>`, every `<orio-button>` will submit unless you pass
|
|
50
|
+
`type="button"`.
|
|
51
|
+
- **Loading hides the icon and the icon-right slot.** No way to keep
|
|
52
|
+
the trailing icon while showing a spinner — render the spinner
|
|
53
|
+
yourself in `#icon-right` if you need that.
|
|
54
|
+
- **No `aria-busy` on loading.** Set it via `$attrs` if you need
|
|
55
|
+
screen-reader signal.
|
|
56
|
+
|
|
57
|
+
## Quick reference
|
|
58
|
+
|
|
59
|
+
```vue
|
|
60
|
+
<template>
|
|
61
|
+
<orio-button @click="onSave" :loading="saving">
|
|
62
|
+
{{ $t("common.save") }}
|
|
63
|
+
</orio-button>
|
|
64
|
+
|
|
65
|
+
<orio-button variant="secondary" icon="trash" @click="onDelete">
|
|
66
|
+
{{ $t("common.delete") }}
|
|
67
|
+
</orio-button>
|
|
68
|
+
|
|
69
|
+
<orio-button variant="subdued" icon="close" aria-label="Close" />
|
|
70
|
+
</template>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Related
|
|
74
|
+
|
|
75
|
+
- `<orio-nav-button>` — link-styled button with `active` state.
|
|
76
|
+
- `<orio-loading-spinner>` — used internally when `loading` is true.
|
|
77
|
+
- `<orio-icon>` — used internally for the `icon` prop and slots.
|
|
78
|
+
- Public API reference: `docs/components/button.md`.
|
|
@@ -3,13 +3,14 @@ interface Props extends ControlProps {
|
|
|
3
3
|
variant?: "primary" | "secondary" | "subdued";
|
|
4
4
|
icon?: string;
|
|
5
5
|
loading?: boolean;
|
|
6
|
-
disabled?: boolean;
|
|
7
6
|
}
|
|
8
|
-
declare var __VLS_13: {}, __VLS_20: {};
|
|
7
|
+
declare var __VLS_13: {}, __VLS_20: {}, __VLS_22: {};
|
|
9
8
|
type __VLS_Slots = {} & {
|
|
10
9
|
icon?: (props: typeof __VLS_13) => any;
|
|
11
10
|
} & {
|
|
12
11
|
default?: (props: typeof __VLS_20) => any;
|
|
12
|
+
} & {
|
|
13
|
+
'icon-right'?: (props: typeof __VLS_22) => any;
|
|
13
14
|
};
|
|
14
15
|
declare const __VLS_base: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
15
16
|
click: (event: PointerEvent) => any;
|
|
@@ -4,7 +4,6 @@ const props = defineProps({
|
|
|
4
4
|
variant: { type: String, required: false, default: "primary" },
|
|
5
5
|
icon: { type: String, required: false },
|
|
6
6
|
loading: { type: Boolean, required: false },
|
|
7
|
-
disabled: { type: Boolean, required: false },
|
|
8
7
|
appearance: { type: String, required: false },
|
|
9
8
|
error: { type: [String, null], required: false },
|
|
10
9
|
group: { type: Boolean, required: false },
|
|
@@ -12,7 +11,13 @@ const props = defineProps({
|
|
|
12
11
|
label: { type: String, required: false },
|
|
13
12
|
layout: { type: String, required: false },
|
|
14
13
|
size: { type: String, required: false },
|
|
15
|
-
fill: { type: Boolean, required: false }
|
|
14
|
+
fill: { type: Boolean, required: false },
|
|
15
|
+
tabindex: { type: [Number, String], required: false },
|
|
16
|
+
focusKey: { type: String, required: false },
|
|
17
|
+
disabled: { type: Boolean, required: false },
|
|
18
|
+
required: { type: Boolean, required: false },
|
|
19
|
+
name: { type: String, required: false },
|
|
20
|
+
ariaLabel: { type: String, required: false }
|
|
16
21
|
});
|
|
17
22
|
const { loading, disabled } = toRefs(props);
|
|
18
23
|
const slots = useSlots();
|
|
@@ -39,21 +44,25 @@ function onMouseleave(event) {
|
|
|
39
44
|
</script>
|
|
40
45
|
|
|
41
46
|
<template>
|
|
42
|
-
<orio-control-element v-bind="props">
|
|
47
|
+
<orio-control-element v-slot="{ control }" v-bind="props">
|
|
43
48
|
<button
|
|
44
|
-
v-bind="
|
|
49
|
+
v-bind="{ ...$attrs, ...control }"
|
|
45
50
|
:class="[variant, 'gradient-hover', { 'icon-only': isIconOnly }]"
|
|
46
|
-
:disabled
|
|
47
51
|
@click="click"
|
|
48
52
|
@mousedown="onMousedown"
|
|
49
53
|
@mouseup="onMouseup"
|
|
50
54
|
@mouseleave="onMouseleave"
|
|
51
55
|
>
|
|
52
56
|
<orio-loading-spinner v-if="loading" />
|
|
53
|
-
<
|
|
54
|
-
<
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
<template v-else>
|
|
58
|
+
<slot name="icon">
|
|
59
|
+
<orio-icon v-if="icon" :name="icon" />
|
|
60
|
+
</slot>
|
|
61
|
+
|
|
62
|
+
<slot />
|
|
63
|
+
|
|
64
|
+
<slot name="icon-right" />
|
|
65
|
+
</template>
|
|
57
66
|
</button>
|
|
58
67
|
</orio-control-element>
|
|
59
68
|
</template>
|
|
@@ -73,9 +82,8 @@ button {
|
|
|
73
82
|
user-select: none;
|
|
74
83
|
}
|
|
75
84
|
button.icon-only {
|
|
76
|
-
padding: 0;
|
|
77
|
-
border-radius: 50%;
|
|
78
85
|
line-height: 0;
|
|
86
|
+
aspect-ratio: 1;
|
|
79
87
|
}
|
|
80
88
|
button:disabled, button:disabled:hover {
|
|
81
89
|
background-color: var(--color-accent-soft-base);
|
|
@@ -3,13 +3,14 @@ interface Props extends ControlProps {
|
|
|
3
3
|
variant?: "primary" | "secondary" | "subdued";
|
|
4
4
|
icon?: string;
|
|
5
5
|
loading?: boolean;
|
|
6
|
-
disabled?: boolean;
|
|
7
6
|
}
|
|
8
|
-
declare var __VLS_13: {}, __VLS_20: {};
|
|
7
|
+
declare var __VLS_13: {}, __VLS_20: {}, __VLS_22: {};
|
|
9
8
|
type __VLS_Slots = {} & {
|
|
10
9
|
icon?: (props: typeof __VLS_13) => any;
|
|
11
10
|
} & {
|
|
12
11
|
default?: (props: typeof __VLS_20) => any;
|
|
12
|
+
} & {
|
|
13
|
+
'icon-right'?: (props: typeof __VLS_22) => any;
|
|
13
14
|
};
|
|
14
15
|
declare const __VLS_base: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
15
16
|
click: (event: PointerEvent) => any;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
kind: component
|
|
3
|
+
category: Date
|
|
4
|
+
purpose: month calendar, date grid, day picker UI
|
|
5
|
+
short: month grid with roving-focus keyboard a11y
|
|
6
|
+
invariants: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Calendar — agent-only invariants
|
|
10
|
+
|
|
11
|
+
`<orio-calendar>` is the month-grid primitive. `date/Picker.vue` and
|
|
12
|
+
`date/RangePicker.vue` compose it inside a popover.
|
|
13
|
+
|
|
14
|
+
## Invariants
|
|
15
|
+
|
|
16
|
+
- **All dates are ISO `YYYY-MM-DD` strings** at the API boundary
|
|
17
|
+
(`selected`, `markers.start`/`end`, `getMarker`, `isDisabled`, `@select`,
|
|
18
|
+
`@dayEnter`). Never pass `Date` objects.
|
|
19
|
+
- **Two reactive states**:
|
|
20
|
+
- `selected` (prop) — the picked day. Calendar does not own it; emit
|
|
21
|
+
`@select` and let the parent update its v-model.
|
|
22
|
+
- `anchor` (v-model:anchor) — the visible month. Calendar owns this when
|
|
23
|
+
uncontrolled, derived from `selected` if not provided. Pass it as
|
|
24
|
+
`v-model:anchor` if you need cross-component sync (RangePicker uses
|
|
25
|
+
this to keep two months in lockstep).
|
|
26
|
+
- **Keyboard a11y via `useRovingGrid`.** Arrow keys, Home/End, PageUp/Down
|
|
27
|
+
navigate. Only one day cell is in the tab order at a time. Do not add
|
|
28
|
+
manual `tabindex` to day cells from outside.
|
|
29
|
+
- **42-cell grid (6 rows × 7 cols).** Leading/trailing days from neighbour
|
|
30
|
+
months are rendered with `inMonth: false`. Selection and disabled checks
|
|
31
|
+
apply to them too — `isDisabled` is called for every cell.
|
|
32
|
+
- **Markers are matched in reverse order** — the last marker in the array
|
|
33
|
+
wins on overlap. `getMarker` takes precedence over `markers[]` when both
|
|
34
|
+
are provided.
|
|
35
|
+
- **`weekStartsOn`** is `0` (Sunday) or `1` (Monday, default). Weekday
|
|
36
|
+
header labels are derived via `Intl.DateTimeFormat` in the active i18n
|
|
37
|
+
locale.
|
|
38
|
+
|
|
39
|
+
## Gotchas
|
|
40
|
+
|
|
41
|
+
- Disabled-day logic should be reactive — `isDisabled` is called inside a
|
|
42
|
+
computed. Wrap any external state it reads in `computed`/`ref` or it will
|
|
43
|
+
not re-render on change.
|
|
44
|
+
- The Calendar emits `@dayEnter` on hover/keyboard-focus, **not** on
|
|
45
|
+
selection. Use for range-picking previews; selection is only `@select`.
|
|
46
|
+
- i18n keys used: `calendar.previousYear`, `calendar.previousMonth`,
|
|
47
|
+
`calendar.nextMonth`, `calendar.nextYear`. Override these if you ship a
|
|
48
|
+
locale not bundled in `runtime/i18n/`.
|
|
49
|
+
|
|
50
|
+
## Quick reference
|
|
51
|
+
|
|
52
|
+
```vue
|
|
53
|
+
<orio-calendar
|
|
54
|
+
:selected="iso"
|
|
55
|
+
:markers="[{ variant: 'accent', start: '2026-06-01', end: '2026-06-07' }]"
|
|
56
|
+
:is-disabled="(iso) => iso < todayIso"
|
|
57
|
+
@select="iso = $event"
|
|
58
|
+
/>
|
|
59
|
+
```
|