orio-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +237 -0
  3. package/dist/module.cjs +5 -0
  4. package/dist/module.d.mts +3 -0
  5. package/dist/module.d.ts +3 -0
  6. package/dist/module.json +12 -0
  7. package/dist/module.mjs +16 -0
  8. package/dist/runtime/assets/css/animation.css +1 -0
  9. package/dist/runtime/assets/css/colors.css +1 -0
  10. package/dist/runtime/assets/css/cool-gradient-hover.css +23 -0
  11. package/dist/runtime/assets/css/main.css +1 -0
  12. package/dist/runtime/assets/css/scroll.css +1 -0
  13. package/dist/runtime/components/Button.vue +102 -0
  14. package/dist/runtime/components/CheckBox.vue +93 -0
  15. package/dist/runtime/components/ControlElement.vue +39 -0
  16. package/dist/runtime/components/DashedContainer.vue +59 -0
  17. package/dist/runtime/components/DatePicker.vue +30 -0
  18. package/dist/runtime/components/DateRangePicker.vue +73 -0
  19. package/dist/runtime/components/EmptyState.vue +81 -0
  20. package/dist/runtime/components/Icon.vue +40 -0
  21. package/dist/runtime/components/Input.vue +48 -0
  22. package/dist/runtime/components/LoadingSpinner.vue +6 -0
  23. package/dist/runtime/components/Modal.vue +69 -0
  24. package/dist/runtime/components/Popover.vue +249 -0
  25. package/dist/runtime/components/Selector.vue +208 -0
  26. package/dist/runtime/components/Tag.vue +21 -0
  27. package/dist/runtime/components/Textarea.vue +53 -0
  28. package/dist/runtime/components/view/Dates.vue +59 -0
  29. package/dist/runtime/components/view/Separator.vue +26 -0
  30. package/dist/runtime/components/view/Text.vue +79 -0
  31. package/dist/runtime/composables/index.d.ts +4 -0
  32. package/dist/runtime/composables/index.js +4 -0
  33. package/dist/runtime/composables/useApi.d.ts +10 -0
  34. package/dist/runtime/composables/useApi.js +9 -0
  35. package/dist/runtime/composables/useFuzzySearch.d.ts +10 -0
  36. package/dist/runtime/composables/useFuzzySearch.js +22 -0
  37. package/dist/runtime/composables/useModal.d.ts +15 -0
  38. package/dist/runtime/composables/useModal.js +28 -0
  39. package/dist/runtime/composables/useTheme.d.ts +6 -0
  40. package/dist/runtime/composables/useTheme.js +23 -0
  41. package/dist/runtime/index.d.ts +20 -0
  42. package/dist/runtime/index.js +20 -0
  43. package/dist/runtime/utils/icon-registry.d.ts +2 -0
  44. package/dist/runtime/utils/icon-registry.js +26 -0
  45. package/dist/types.d.mts +7 -0
  46. package/dist/types.d.ts +7 -0
  47. package/nuxt.config.ts +38 -0
  48. package/package.json +99 -0
  49. package/src/module.ts +16 -0
  50. package/src/runtime/assets/css/animation.css +88 -0
  51. package/src/runtime/assets/css/colors.css +142 -0
  52. package/src/runtime/assets/css/cool-gradient-hover.scss +33 -0
  53. package/src/runtime/assets/css/main.css +11 -0
  54. package/src/runtime/assets/css/scroll.css +46 -0
  55. package/src/runtime/components/Button.vue +110 -0
  56. package/src/runtime/components/CheckBox.vue +103 -0
  57. package/src/runtime/components/ControlElement.vue +42 -0
  58. package/src/runtime/components/DashedContainer.vue +60 -0
  59. package/src/runtime/components/DatePicker.vue +84 -0
  60. package/src/runtime/components/DateRangePicker.vue +74 -0
  61. package/src/runtime/components/EmptyState.vue +87 -0
  62. package/src/runtime/components/Icon.vue +51 -0
  63. package/src/runtime/components/Input.vue +54 -0
  64. package/src/runtime/components/LoadingSpinner.vue +6 -0
  65. package/src/runtime/components/Modal.vue +111 -0
  66. package/src/runtime/components/Popover.vue +249 -0
  67. package/src/runtime/components/Selector.vue +224 -0
  68. package/src/runtime/components/Tag.vue +45 -0
  69. package/src/runtime/components/Textarea.vue +59 -0
  70. package/src/runtime/components/view/Dates.vue +61 -0
  71. package/src/runtime/components/view/Separator.vue +30 -0
  72. package/src/runtime/components/view/Text.vue +83 -0
  73. package/src/runtime/composables/index.ts +4 -0
  74. package/src/runtime/composables/useApi.ts +26 -0
  75. package/src/runtime/composables/useFuzzySearch.ts +51 -0
  76. package/src/runtime/composables/useModal.ts +47 -0
  77. package/src/runtime/composables/useTheme.ts +31 -0
  78. package/src/runtime/index.ts +25 -0
  79. package/src/runtime/utils/icon-registry.ts +41 -0
@@ -0,0 +1,208 @@
1
+ <script setup lang="ts" generic="T extends object">
2
+ import { computed, toRefs } from 'vue';
3
+
4
+ export type SelectableOption<T extends object = object> = string | T;
5
+
6
+ export interface SelectProps<T extends object = object> {
7
+ options: SelectableOption[];
8
+ multiple?: boolean;
9
+ field?: string;
10
+ optionName?: string;
11
+ placeholder?: string;
12
+ }
13
+
14
+ const props = withDefaults(defineProps<SelectProps>(), {
15
+ placeholder: 'Select an option',
16
+ field: 'id',
17
+ });
18
+
19
+ const { field, optionName, placeholder } = toRefs(props);
20
+
21
+ const modelValue = defineModel<SelectableOption | SelectableOption[] | null | undefined>({
22
+ required: true,
23
+ });
24
+
25
+ // Key to the object when option is not 'string'
26
+ const key = computed(() => field.value as Extract<keyof T, string>);
27
+ const label = computed(() => optionName.value as Extract<keyof T, string>);
28
+
29
+ const flatModalValue = computed(() => {
30
+ if (!modelValue.value) return null;
31
+ if (!props.multiple || !Array.isArray(modelValue.value))
32
+ return typeof modelValue.value === 'string'
33
+ ? modelValue.value
34
+ : (modelValue.value as T)[key.value];
35
+ return modelValue.value.map((option) =>
36
+ typeof option === 'string' ? option : (option as T)[key.value]
37
+ );
38
+ });
39
+
40
+ function toggleOption(option: SelectableOption, toggle: () => void) {
41
+ if (props.multiple) {
42
+ if (Array.isArray(modelValue.value)) {
43
+ const index = modelValue.value.findIndex((opt) =>
44
+ typeof option === 'string' ? option === opt : opt[key.value] === (option as T)[key.value]
45
+ );
46
+ if (index > -1) {
47
+ modelValue.value.splice(index, 1);
48
+ } else {
49
+ modelValue.value.push(option);
50
+ }
51
+ } else {
52
+ modelValue.value = [option];
53
+ }
54
+ } else {
55
+ modelValue.value = option;
56
+ // should later be turned off with some additional interaction modes
57
+ toggle();
58
+ }
59
+ }
60
+
61
+ function isOptionSelected(option: SelectableOption): boolean {
62
+ if (typeof option === 'string') return modelValue.value === option;
63
+ return !!(
64
+ flatModalValue.value &&
65
+ (flatModalValue.value === (option as T)[key.value] ||
66
+ (flatModalValue.value as string[]).includes((option as T)[key.value] as string))
67
+ );
68
+ }
69
+
70
+ function getOptionLabel(option: SelectableOption | undefined): string {
71
+ if (!option) return placeholder.value;
72
+ if (typeof option === 'string') return option;
73
+ if (optionName.value) return String((option as T)[label.value]);
74
+ return JSON.stringify(option);
75
+ }
76
+
77
+ function getOptionKey(option: SelectableOption): string | number {
78
+ if (typeof option === 'string') return option;
79
+ return String((option as T)[key.value]);
80
+ }
81
+
82
+ const selectorAttrs = computed(() => ({ getOptionKey, getOptionLabel }));
83
+ </script>
84
+
85
+ <template>
86
+ <orio-control-element>
87
+ <orio-popover position="bottom-right" :offset="5">
88
+ <template #default="{ toggle }">
89
+ <slot name="trigger" :toggle>
90
+ <div class="selector-trigger">
91
+ <slot name="trigger-content" :toggle v-bind="selectorAttrs" :attrs="$attrs">
92
+ <div class="trigger-content">
93
+ <slot name="trigger-label" :toggle v-bind="selectorAttrs" :attrs="$attrs">
94
+ <template v-if="!props.multiple">
95
+ {{ getOptionLabel(modelValue as T) }}
96
+ </template>
97
+ <template v-else-if="Array.isArray(modelValue)">
98
+ <span> {{ modelValue!.length }} selected </span>
99
+ </template>
100
+ </slot>
101
+ </div>
102
+ <orio-icon name="chevron-down" />
103
+ </slot>
104
+ </div>
105
+ </slot>
106
+ </template>
107
+
108
+ <template #content="{ toggle }">
109
+ <div class="selector-content">
110
+ <ul v-if="options.length">
111
+ <li
112
+ v-for="option in options"
113
+ :key="getOptionKey(option)"
114
+ :class="{ selected: isOptionSelected(option) }"
115
+ @click="toggleOption(option, toggle)"
116
+ >
117
+ <slot
118
+ name="option"
119
+ :option
120
+ :toggle
121
+ :selected="isOptionSelected(option)"
122
+ v-bind="selectorAttrs"
123
+ >
124
+ {{ getOptionLabel(option) }}
125
+ </slot>
126
+ </li>
127
+ </ul>
128
+ <slot v-else name="no-options">
129
+ <orio-empty-state title="No options found" size="small" />
130
+ </slot>
131
+ <slot name="options-addon" />
132
+ </div>
133
+ </template>
134
+ </orio-popover>
135
+ </orio-control-element>
136
+ </template>
137
+
138
+ <style scoped>
139
+ .selector-trigger {
140
+ z-index: 1;
141
+ min-height: 1.5rem;
142
+ user-select: none;
143
+ display: flex;
144
+ align-items: center;
145
+ justify-content: space-between;
146
+ cursor: pointer;
147
+ background: var(--color-bg);
148
+ border: 1px solid var(--color-border);
149
+ border-radius: 6px;
150
+ padding: 0.5rem 0.75rem;
151
+ font-size: 0.95rem;
152
+ color: var(--color-text);
153
+ transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
154
+ }
155
+ .selector-trigger:hover {
156
+ border-color: var(--color-accent);
157
+ background-color: var(--color-surface); /* subtle lift */
158
+ }
159
+ .selector-trigger:focus-within {
160
+ border-color: var(--color-accent);
161
+ box-shadow: 0 0 0 2px var(--color-surface);
162
+ }
163
+ .selector-trigger .icon {
164
+ color: var(--color-muted);
165
+ transition: color 0.2s ease;
166
+ }
167
+ .selector-trigger:hover .icon {
168
+ color: var(--color-accent);
169
+ }
170
+
171
+ .selector-content {
172
+ min-width: 15rem;
173
+ max-height: 20rem;
174
+ overflow: auto;
175
+ background: var(--color-bg);
176
+ border: 1px solid var(--color-border);
177
+ border-radius: 6px;
178
+ margin-top: 0.25rem;
179
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
180
+ }
181
+ .selector-content ul {
182
+ list-style: none;
183
+ padding: 0;
184
+ margin: 0;
185
+ }
186
+ .selector-content ul li {
187
+ padding: 0.5rem 0.75rem;
188
+ cursor: pointer;
189
+ transition: background-color 0.15s ease, color 0.15s ease;
190
+ color: var(--color-text);
191
+ }
192
+ .selector-content ul li:hover {
193
+ background-color: var(--color-surface); /* neutral lift */
194
+ }
195
+ .selector-content ul li.selected {
196
+ background-color: var(--color-accent);
197
+ color: var(--color-accent-soft);
198
+ font-weight: 500;
199
+ }
200
+
201
+ .trigger-content {
202
+ width: 100%;
203
+ }
204
+
205
+ :deep(.popover) {
206
+ width: 100%;
207
+ }
208
+ </style>
@@ -0,0 +1,21 @@
1
+ <script setup lang="ts">
2
+ export type TagStyle = 'neutral' | 'accent';
3
+
4
+ interface Props {
5
+ text: string;
6
+ variant?: TagStyle;
7
+ }
8
+ withDefaults(defineProps<Props>(), {
9
+ variant: 'neutral',
10
+ });
11
+ </script>
12
+
13
+ <template>
14
+ <span class="tag" :class="`tag--${variant}`">
15
+ {{ text }}
16
+ </span>
17
+ </template>
18
+
19
+ <style scoped>
20
+ .tag{border:1px solid transparent;border-radius:1rem;display:inline-block;font-size:.8rem;font-weight:500;line-height:1;max-height:1rem;padding:.25rem .6rem;-webkit-user-select:none;-moz-user-select:none;user-select:none}.tag--neutral{background-color:var(--color-surface);border-color:color-mix(in srgb,var(--color-border) 80%,var(--color-accent) 20%);color:var(--color-muted)}.tag--accent{background-color:var(--color-accent-soft);border-color:var(--color-accent-border);color:var(--color-accent)}
21
+ </style>
@@ -0,0 +1,53 @@
1
+ <script setup lang="ts">
2
+ import { useAttrs } from 'vue';
3
+
4
+ const attrs = useAttrs();
5
+ defineEmits<{
6
+ (e: 'input', value: string): void;
7
+ }>();
8
+
9
+ const modelValue = defineModel<string>({ default: '' });
10
+ </script>
11
+
12
+ <template>
13
+ <orio-control-element v-bind="attrs">
14
+ <textarea
15
+ v-bind="attrs"
16
+ v-model="modelValue"
17
+ rows="4"
18
+ class="textarea"
19
+ />
20
+ </orio-control-element>
21
+ </template>
22
+
23
+ <style scoped>
24
+ .textarea {
25
+ width: 100%;
26
+ padding: 0.5rem 0.75rem;
27
+ border: 1px solid var(--color-border);
28
+ border-radius: 4px;
29
+ font-size: 1rem;
30
+ line-height: 1.4;
31
+ color: var(--color-text);
32
+ background-color: var(--color-bg);
33
+ box-sizing: border-box;
34
+ resize: vertical; /* Let user resize vertically only */
35
+ transition: border-color 0.2s ease, box-shadow 0.2s ease;
36
+ }
37
+ .textarea::placeholder {
38
+ color: var(--color-muted);
39
+ }
40
+ .textarea:hover {
41
+ border-color: var(--color-accent);
42
+ }
43
+ .textarea:focus {
44
+ border-color: var(--color-accent);
45
+ box-shadow: 0 0 0 2px var(--color-accent-soft);
46
+ outline: none;
47
+ }
48
+ .textarea:disabled {
49
+ background-color: var(--color-surface);
50
+ color: var(--color-muted);
51
+ cursor: not-allowed;
52
+ }
53
+ </style>
@@ -0,0 +1,59 @@
1
+ <script setup lang="ts">
2
+ import { computed, toRefs } from 'vue';
3
+
4
+ export interface ResumeDate {
5
+ startDate: string;
6
+ endDate?: string | null; // undefined - mean single date, null - means "Present"
7
+ }
8
+
9
+ interface Props {
10
+ dates: ResumeDate;
11
+ month?: boolean; // Optional prop to indicate if the date should be displayed as month/year
12
+ size?: 'small' | 'medium' | 'large';
13
+ type?: 'text' | 'title' | 'subtitle' | 'italics';
14
+ }
15
+
16
+ const props = withDefaults(defineProps<Props>(), {
17
+ size: 'small',
18
+ type: 'italics',
19
+ });
20
+
21
+ const { dates } = toRefs(props);
22
+
23
+ function formatMonthYear(value: string) {
24
+ if (!value) return '';
25
+ if (!props.month)
26
+ return new Intl.DateTimeFormat('en-US', {
27
+ day: 'numeric',
28
+ month: 'short',
29
+ year: 'numeric',
30
+ }).format(new Date(value));
31
+ return new Intl.DateTimeFormat('en-US', {
32
+ month: 'short',
33
+ year: 'numeric',
34
+ }).format(new Date(value));
35
+ }
36
+
37
+ const startDate = computed(() => formatMonthYear(dates.value.startDate));
38
+
39
+ const endDate = computed(() => {
40
+ if (dates.value.endDate === undefined) return null;
41
+ return dates.value.endDate !== null
42
+ ? formatMonthYear(dates.value.endDate)
43
+ : 'Present';
44
+ });
45
+ </script>
46
+
47
+ <template>
48
+ <div class="view-date">
49
+ <orio-view-text :model-value="startDate" :type :size />
50
+ <template v-if="endDate">
51
+ <span v-if="startDate"> - </span>
52
+ <orio-view-text :model-value="endDate" :type :size />
53
+ </template>
54
+ </div>
55
+ </template>
56
+
57
+ <style scoped>
58
+ .view-date *{display:inline}
59
+ </style>
@@ -0,0 +1,26 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue';
3
+
4
+ interface Props {
5
+ style?: 'dotted' | 'dashed' | 'solid' | 'double' | 'groove' | 'ridge';
6
+ size?: number | string;
7
+ margin?: number | string;
8
+ }
9
+
10
+ const props = withDefaults(defineProps<Props>(), {
11
+ style: 'solid',
12
+ size: 1,
13
+ margin: 1,
14
+ });
15
+
16
+ const sizePx = computed(() => `${props.size}px`);
17
+ const margin = computed(() => `${props.margin}rem`);
18
+ </script>
19
+
20
+ <template>
21
+ <div />
22
+ </template>
23
+
24
+ <style scoped>
25
+ div{border-block-end:v-bind(sizePx) v-bind(style) var(--color-border);margin-block:v-bind(margin);width:100%}
26
+ </style>
@@ -0,0 +1,79 @@
1
+ <script setup lang="ts">
2
+ import { computed, useAttrs } from 'vue';
3
+
4
+ export type TextTypes = 'text' | 'title' | 'subtitle' | 'italics';
5
+
6
+ export interface TextProps {
7
+ type?: TextTypes;
8
+ size?: 'small' | 'medium' | 'large' | 'extra-large';
9
+ uppercase?: boolean;
10
+ icon?: string | null;
11
+ lineClamp?: number | string;
12
+ }
13
+ const props = withDefaults(defineProps<TextProps>(), {
14
+ type: 'text',
15
+ size: 'medium',
16
+ uppercase: false,
17
+ icon: null,
18
+ lineClamp: undefined,
19
+ });
20
+ const attrs = useAttrs();
21
+ const modelValue = defineModel<string>();
22
+
23
+ const clampLines = computed(() => Number(props.lineClamp ?? 1));
24
+ </script>
25
+
26
+ <template>
27
+ <div :class="[type, size, { uppercase, clamp: !!lineClamp }]" v-bind="attrs">
28
+ <orio-icon v-if="icon" :name="icon" />
29
+ <slot>
30
+ {{ modelValue }}
31
+ </slot>
32
+ </div>
33
+ </template>
34
+
35
+ <style scoped>
36
+ div {
37
+ white-space: pre-wrap;
38
+ display: flex;
39
+ align-items: center;
40
+ gap: 0.25rem;
41
+ }
42
+ div.clamp {
43
+ display: -webkit-box;
44
+ overflow: hidden;
45
+ line-clamp: v-bind(clampLines);
46
+ -webkit-line-clamp: v-bind(clampLines);
47
+ -webkit-box-orient: vertical;
48
+ }
49
+ div.uppercase {
50
+ text-transform: uppercase;
51
+ }
52
+ div.text {
53
+ color: var(--color-text);
54
+ }
55
+ div.title {
56
+ font-weight: bold;
57
+ color: var(--color-text);
58
+ }
59
+ div.subtitle {
60
+ font-weight: semi-bold;
61
+ color: var(--color-muted);
62
+ }
63
+ div.italics {
64
+ font-style: italic;
65
+ color: var(--color-muted);
66
+ }
67
+ div.small {
68
+ font-size: 0.75rem;
69
+ }
70
+ div.medium {
71
+ font-size: 0.875rem;
72
+ }
73
+ div.large {
74
+ font-size: 1.25rem;
75
+ }
76
+ div.extra-large {
77
+ font-size: 1.75rem;
78
+ }
79
+ </style>
@@ -0,0 +1,4 @@
1
+ export { useApi, type ApiOptions, type RequestBody, type RequestMethod } from './useApi.js';
2
+ export { useFuzzySearch } from './useFuzzySearch.js';
3
+ export { useModal, type ModalProps, type OriginRect } from './useModal.js';
4
+ export { useTheme } from './useTheme.js';
@@ -0,0 +1,4 @@
1
+ export { useApi } from "./useApi.js";
2
+ export { useFuzzySearch } from "./useFuzzySearch.js";
3
+ export { useModal } from "./useModal.js";
4
+ export { useTheme } from "./useTheme.js";
@@ -0,0 +1,10 @@
1
+ export type RequestBody = Record<string, unknown>;
2
+ export type RequestMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
3
+ export interface ApiOptions {
4
+ method?: RequestMethod;
5
+ body?: RequestBody;
6
+ signal?: AbortSignal;
7
+ query?: Record<string, unknown>;
8
+ }
9
+ export declare function useApi<T = unknown>(url: string): Promise<T>;
10
+ export declare function useApi<T = unknown>(url: string, options: ApiOptions): Promise<T>;
@@ -0,0 +1,9 @@
1
+ import { $fetch } from "ofetch";
2
+ export async function useApi(url, options) {
3
+ return await $fetch(url, {
4
+ method: options?.method || "GET",
5
+ body: options?.body,
6
+ signal: options?.signal,
7
+ query: options?.query
8
+ });
9
+ }
@@ -0,0 +1,10 @@
1
+ import { type MaybeRef } from 'vue';
2
+ import { useFuse, type FuseOptions } from '@vueuse/integrations/useFuse';
3
+ /**
4
+ * Search using Fuse.js fuzzy search
5
+ * @param dataSource - Array of strings or objects to search
6
+ * @param search - Search query string
7
+ * @param options - Fuse.js options (e.g., { keys: ['name'] })
8
+ */
9
+ export declare function useFuzzySearch(dataSource: MaybeRef<string[]>, search: MaybeRef<string>): ReturnType<typeof useFuse>;
10
+ export declare function useFuzzySearch<T extends object>(dataSource: MaybeRef<T[]>, search: MaybeRef<string>, options: FuseOptions<T>): ReturnType<typeof useFuse>;
@@ -0,0 +1,22 @@
1
+ import { computed, unref } from "vue";
2
+ import { useFuse } from "@vueuse/integrations/useFuse";
3
+ export function useFuzzySearch(dataSource, search, options) {
4
+ const isObjectArray = !!options;
5
+ if (!isObjectArray) {
6
+ const wrappedData = computed(() => {
7
+ const data = unref(dataSource);
8
+ return data.map((str) => ({ value: str }));
9
+ });
10
+ const { results } = useFuse(search, wrappedData, {
11
+ fuseOptions: { keys: ["value"] },
12
+ matchAllWhenSearchEmpty: true
13
+ });
14
+ return computed(() => results.value.map(({ item }) => item.value));
15
+ } else {
16
+ const { results } = useFuse(search, dataSource, {
17
+ fuseOptions: options,
18
+ matchAllWhenSearchEmpty: true
19
+ });
20
+ return computed(() => results.value.map(({ item }) => item));
21
+ }
22
+ }
@@ -0,0 +1,15 @@
1
+ export interface OriginRect {
2
+ x: number;
3
+ y: number;
4
+ width: number;
5
+ height: number;
6
+ }
7
+ export interface ModalProps {
8
+ show: Boolean;
9
+ origin: OriginRect | null;
10
+ 'onUpdate:show': (state: boolean) => void;
11
+ }
12
+ export declare function useModal(): {
13
+ modalProps: import("vue").Ref<any, any>;
14
+ openModal: (event?: MouseEvent) => void;
15
+ };
@@ -0,0 +1,28 @@
1
+ import { ref } from "vue";
2
+ export function useModal() {
3
+ const modalProps = ref({
4
+ show: false,
5
+ origin: null,
6
+ "onUpdate:show": (state) => updateShow(state)
7
+ });
8
+ function updateShow(state) {
9
+ modalProps.value.show = state;
10
+ }
11
+ function openModal(event) {
12
+ modalProps.value.origin = null;
13
+ if (!event) {
14
+ modalProps.value.show = true;
15
+ return;
16
+ }
17
+ const target = event.target;
18
+ const rect = target.getBoundingClientRect();
19
+ modalProps.value.origin = {
20
+ x: rect.left,
21
+ y: rect.top,
22
+ width: rect.width,
23
+ height: rect.height
24
+ };
25
+ modalProps.value.show = true;
26
+ }
27
+ return { modalProps, openModal };
28
+ }
@@ -0,0 +1,6 @@
1
+ export declare function useTheme(): {
2
+ theme: import("@vueuse/shared").RemovableRef<string>;
3
+ setTheme: (name: string) => void;
4
+ mode: import("@vueuse/shared").RemovableRef<string>;
5
+ setMode: (name: string) => void;
6
+ };
@@ -0,0 +1,23 @@
1
+ import { onMounted } from "vue";
2
+ import { useLocalStorage } from "@vueuse/core";
3
+ export function useTheme() {
4
+ const theme = useLocalStorage("orio-theme", "navy");
5
+ const mode = useLocalStorage("orio-mode", "dark");
6
+ function setTheme(name) {
7
+ theme.value = name;
8
+ if (typeof document !== "undefined") {
9
+ document.documentElement.setAttribute("data-theme", name);
10
+ }
11
+ }
12
+ function setMode(name) {
13
+ mode.value = name;
14
+ if (typeof document !== "undefined") {
15
+ document.documentElement.setAttribute("data-mode", name);
16
+ }
17
+ }
18
+ onMounted(() => {
19
+ setTheme(theme.value);
20
+ setMode(mode.value);
21
+ });
22
+ return { theme, setTheme, mode, setMode };
23
+ }
@@ -0,0 +1,20 @@
1
+ export { default as Button } from './components/Button.vue.js';
2
+ export { default as Input } from './components/Input.vue.js';
3
+ export { default as Textarea } from './components/Textarea.vue.js';
4
+ export { default as CheckBox } from './components/CheckBox.vue.js';
5
+ export { default as DatePicker } from './components/DatePicker.vue.js';
6
+ export { default as DateRangePicker } from './components/DateRangePicker.vue.js';
7
+ export { default as Selector } from './components/Selector.vue.js';
8
+ export { default as Tag } from './components/Tag.vue.js';
9
+ export { default as Icon } from './components/Icon.vue.js';
10
+ export { default as LoadingSpinner } from './components/LoadingSpinner.vue.js';
11
+ export { default as Modal } from './components/Modal.vue.js';
12
+ export { default as Popover } from './components/Popover.vue.js';
13
+ export { default as EmptyState } from './components/EmptyState.vue.js';
14
+ export { default as DashedContainer } from './components/DashedContainer.vue.js';
15
+ export { default as ControlElement } from './components/ControlElement.vue.js';
16
+ export { default as ViewText } from './components/view/Text.vue.js';
17
+ export { default as ViewDates } from './components/view/Dates.vue.js';
18
+ export { default as ViewSeparator } from './components/view/Separator.vue.js';
19
+ export * from './composables/index.js';
20
+ export { iconRegistry, type IconName } from './utils/icon-registry.js';
@@ -0,0 +1,20 @@
1
+ export { default as Button } from "./components/Button.vue";
2
+ export { default as Input } from "./components/Input.vue";
3
+ export { default as Textarea } from "./components/Textarea.vue";
4
+ export { default as CheckBox } from "./components/CheckBox.vue";
5
+ export { default as DatePicker } from "./components/DatePicker.vue";
6
+ export { default as DateRangePicker } from "./components/DateRangePicker.vue";
7
+ export { default as Selector } from "./components/Selector.vue";
8
+ export { default as Tag } from "./components/Tag.vue";
9
+ export { default as Icon } from "./components/Icon.vue";
10
+ export { default as LoadingSpinner } from "./components/LoadingSpinner.vue";
11
+ export { default as Modal } from "./components/Modal.vue";
12
+ export { default as Popover } from "./components/Popover.vue";
13
+ export { default as EmptyState } from "./components/EmptyState.vue";
14
+ export { default as DashedContainer } from "./components/DashedContainer.vue";
15
+ export { default as ControlElement } from "./components/ControlElement.vue";
16
+ export { default as ViewText } from "./components/view/Text.vue";
17
+ export { default as ViewDates } from "./components/view/Dates.vue";
18
+ export { default as ViewSeparator } from "./components/view/Separator.vue";
19
+ export * from "./composables/index.js";
20
+ export { iconRegistry } from "./utils/icon-registry.js";
@@ -0,0 +1,2 @@
1
+ export declare const iconRegistry: Record<string, string>;
2
+ export type IconName = keyof typeof iconRegistry;