orio-ui 0.1.0 → 1.0.1

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 (62) hide show
  1. package/nuxt.config.ts +10 -10
  2. package/package.json +12 -17
  3. package/src/module.ts +5 -5
  4. package/src/runtime/components/ControlElement.vue +2 -2
  5. package/src/runtime/components/DashedContainer.vue +1 -6
  6. package/src/runtime/components/Icon.vue +11 -11
  7. package/src/runtime/components/Input.vue +1 -6
  8. package/src/runtime/components/Modal.vue +1 -1
  9. package/src/runtime/components/Popover.vue +8 -1
  10. package/src/runtime/components/Selector.vue +22 -6
  11. package/src/runtime/components/Tag.vue +5 -1
  12. package/src/runtime/components/Textarea.vue +1 -6
  13. package/src/runtime/composables/index.ts +6 -1
  14. package/src/runtime/composables/useApi.ts +8 -2
  15. package/src/runtime/composables/useFuzzySearch.ts +3 -3
  16. package/src/runtime/composables/useModal.ts +3 -3
  17. package/src/runtime/index.ts +20 -20
  18. package/src/runtime/utils/icon-registry.ts +11 -11
  19. package/dist/module.cjs +0 -5
  20. package/dist/module.d.mts +0 -3
  21. package/dist/module.d.ts +0 -3
  22. package/dist/module.json +0 -12
  23. package/dist/module.mjs +0 -16
  24. package/dist/runtime/assets/css/animation.css +0 -1
  25. package/dist/runtime/assets/css/colors.css +0 -1
  26. package/dist/runtime/assets/css/cool-gradient-hover.css +0 -23
  27. package/dist/runtime/assets/css/main.css +0 -1
  28. package/dist/runtime/assets/css/scroll.css +0 -1
  29. package/dist/runtime/components/Button.vue +0 -102
  30. package/dist/runtime/components/CheckBox.vue +0 -93
  31. package/dist/runtime/components/ControlElement.vue +0 -39
  32. package/dist/runtime/components/DashedContainer.vue +0 -59
  33. package/dist/runtime/components/DatePicker.vue +0 -30
  34. package/dist/runtime/components/DateRangePicker.vue +0 -73
  35. package/dist/runtime/components/EmptyState.vue +0 -81
  36. package/dist/runtime/components/Icon.vue +0 -40
  37. package/dist/runtime/components/Input.vue +0 -48
  38. package/dist/runtime/components/LoadingSpinner.vue +0 -6
  39. package/dist/runtime/components/Modal.vue +0 -69
  40. package/dist/runtime/components/Popover.vue +0 -249
  41. package/dist/runtime/components/Selector.vue +0 -208
  42. package/dist/runtime/components/Tag.vue +0 -21
  43. package/dist/runtime/components/Textarea.vue +0 -53
  44. package/dist/runtime/components/view/Dates.vue +0 -59
  45. package/dist/runtime/components/view/Separator.vue +0 -26
  46. package/dist/runtime/components/view/Text.vue +0 -79
  47. package/dist/runtime/composables/index.d.ts +0 -4
  48. package/dist/runtime/composables/index.js +0 -4
  49. package/dist/runtime/composables/useApi.d.ts +0 -10
  50. package/dist/runtime/composables/useApi.js +0 -9
  51. package/dist/runtime/composables/useFuzzySearch.d.ts +0 -10
  52. package/dist/runtime/composables/useFuzzySearch.js +0 -22
  53. package/dist/runtime/composables/useModal.d.ts +0 -15
  54. package/dist/runtime/composables/useModal.js +0 -28
  55. package/dist/runtime/composables/useTheme.d.ts +0 -6
  56. package/dist/runtime/composables/useTheme.js +0 -23
  57. package/dist/runtime/index.d.ts +0 -20
  58. package/dist/runtime/index.js +0 -20
  59. package/dist/runtime/utils/icon-registry.d.ts +0 -2
  60. package/dist/runtime/utils/icon-registry.js +0 -26
  61. package/dist/types.d.mts +0 -7
  62. package/dist/types.d.ts +0 -7
@@ -1,102 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed, toRefs, useAttrs, useSlots } from 'vue';
3
-
4
- interface Props {
5
- type?: 'primary' | 'secondary' | 'subdued';
6
- icon?: string;
7
- loading?: boolean;
8
- disabled?: boolean;
9
- }
10
-
11
- const props = withDefaults(defineProps<Props>(), {
12
- type: 'primary',
13
- });
14
-
15
- const { loading, disabled } = toRefs(props);
16
-
17
- const attrs = useAttrs();
18
- const slots = useSlots();
19
-
20
- const isIconOnly = computed(() => {
21
- const hasIcon = !!props.icon || !!slots.icon;
22
- const hasDefault = !!slots.default;
23
- return hasIcon && !hasDefault;
24
- });
25
-
26
- const emit = defineEmits<{
27
- (e: 'click', event: PointerEvent): void;
28
- }>();
29
-
30
- function click(event: PointerEvent) {
31
- if (loading.value || disabled.value) return;
32
- emit('click', event);
33
- }
34
- </script>
35
-
36
- <template>
37
- <orio-control-element>
38
- <button
39
- v-bind="attrs"
40
- :class="[type, 'gradient-hover', { 'icon-only': isIconOnly }]"
41
- @click="click"
42
- >
43
- <orio-loading-spinner v-if="loading" />
44
- <slot v-else name="icon">
45
- <orio-icon v-if="icon" :name="icon" />
46
- </slot>
47
- <slot />
48
- </button>
49
- </orio-control-element>
50
- </template>
51
-
52
- <style scoped>
53
- button {
54
- background-color: var(--color-accent);
55
- color: var(--color-accent-ink);
56
- border: 1px solid transparent;
57
- border-radius: 4px;
58
- padding: 8px 16px;
59
- cursor: pointer;
60
- display: inline-flex;
61
- align-items: center;
62
- gap: 0.5rem;
63
- user-select: none;
64
- }
65
- button.icon-only {
66
- padding: 0;
67
- border-radius: 50%;
68
- }
69
- button:disabled {
70
- background-color: var(--color-accent-soft);
71
- color: var(--color-muted);
72
- border-color: var(--color-accent-border);
73
- cursor: not-allowed;
74
- }
75
- button:active {
76
- border: 1px solid var(--color-accent-border);
77
- }
78
- button.primary {
79
- --gh-color: var(--color-accent);
80
- }
81
- button.secondary {
82
- background-color: transparent;
83
- border: 1px solid var(--color-accent);
84
- color: var(--color-accent);
85
- }
86
- button.secondary:hover {
87
- color: var(--color-accent-hover);
88
- }
89
- button.subdued {
90
- background-color: transparent;
91
- color: var(--color-accent);
92
- }
93
- button.subdued:hover {
94
- color: var(--color-accent-hover);
95
- }
96
- button:active {
97
- border-color: var(--color-accent-border) !important;
98
- }
99
- button:hover {
100
- color: var(--color-accent-ink);
101
- }
102
- </style>
@@ -1,93 +0,0 @@
1
- <script setup lang="ts">
2
- const modelValue = defineModel<boolean>({ required: false });
3
-
4
- defineProps<{
5
- checkedIcon?: string; // optional: pass icon name for checked state
6
- uncheckedIcon?: string; // optional: pass icon name for unchecked state
7
- }>();
8
- </script>
9
-
10
- <template>
11
- <orio-control-element class="checkbox">
12
- <label class="checkbox-label">
13
- <input
14
- v-model="modelValue"
15
- type="checkbox"
16
- class="checkbox-input"
17
- tabindex="-1"
18
- />
19
- <span
20
- class="checkbox-box"
21
- :class="{
22
- defaultChecked: !checkedIcon,
23
- defaultUnchecked: !uncheckedIcon,
24
- }"
25
- >
26
- <slot name="icon" :checked="modelValue">
27
- <orio-icon v-if="modelValue && checkedIcon" :name="checkedIcon" />
28
- <orio-icon
29
- v-else-if="!modelValue && uncheckedIcon"
30
- :name="uncheckedIcon"
31
- />
32
- </slot>
33
- </span>
34
- <slot />
35
- </label>
36
- </orio-control-element>
37
- </template>
38
-
39
- <style scoped>
40
- .checkbox {
41
- --box-size: 1rem;
42
- }
43
- .checkbox-label {
44
- position: relative;
45
- user-select: none;
46
- display: inline-flex;
47
- align-items: center;
48
- gap: 0.4rem;
49
- cursor: pointer;
50
- font-size: 0.9rem;
51
- color: var(--color-text);
52
- }
53
- .checkbox-input {
54
- position: absolute;
55
- inset: 0;
56
- width: var(--box-size);
57
- height: 1rem;
58
- margin: 0;
59
- opacity: 0;
60
- }
61
- .checkbox-box {
62
- width: var(--box-size);
63
- height: var(--box-size);
64
- border: 2px solid var(--color-border);
65
- border-radius: 4px;
66
- background-color: var(--color-bg);
67
- display: inline-flex;
68
- align-items: center;
69
- justify-content: center;
70
- transition: background-color 0.2s ease, border-color 0.2s ease;
71
- }
72
- .checkbox .checkbox-input:checked + .checkbox-box {
73
- background-color: var(--color-accent);
74
- border-color: var(--color-accent);
75
- }
76
- .checkbox .checkbox-input:checked + .checkbox-box.defaultChecked::after {
77
- content: "";
78
- width: 0.3rem;
79
- height: 0.6rem;
80
- position: relative;
81
- bottom: 0.1rem;
82
- border: solid var(--color-accent-ink);
83
- border-width: 0 2px 2px 0;
84
- transform: rotate(45deg);
85
- }
86
- .checkbox-label:hover .checkbox-box {
87
- border-color: var(--color-accent);
88
- }
89
- .checkbox .checkbox-input:focus-visible + .checkbox-box {
90
- outline: 2px solid var(--color-accent);
91
- outline-offset: 2px;
92
- }
93
- </style>
@@ -1,39 +0,0 @@
1
- <script setup lang="ts">
2
- export interface ControlProps {
3
- /**
4
- * Minimal will reset margin and remove border and box shadow from every element inside the slot
5
- */
6
- appearance?: "normal" | "minimal";
7
- }
8
-
9
- withDefaults(defineProps<ControlProps>(), {
10
- appearance: "normal",
11
- });
12
- </script>
13
-
14
- <template>
15
- <div class="control" :class="[appearance]">
16
- <label v-if="$attrs.label" class="control-label">{{ $attrs.label }}</label>
17
- <div class="slot-wrapper" v-bind="$attrs">
18
- <slot />
19
- </div>
20
- </div>
21
- </template>
22
-
23
- <style scoped>
24
- .control {
25
- margin: 0.5rem;
26
- }
27
- .control .control-label {
28
- user-select: none;
29
- }
30
- .control.minimal {
31
- margin: 0;
32
- }
33
- .control.minimal .slot-wrapper :first-child {
34
- border: 0;
35
- }
36
- .control.minimal .slot-wrapper :first-child:focus {
37
- box-shadow: none;
38
- }
39
- </style>
@@ -1,59 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed } from 'vue';
3
-
4
- interface Props {
5
- icon?: string;
6
- text?: string;
7
- size?: 'small' | 'medium' | 'large';
8
- }
9
- const props = withDefaults(defineProps<Props>(), {
10
- size: 'medium',
11
- });
12
- defineEmits(['click']);
13
-
14
- const iconSize = computed(() => {
15
- switch (props.size) {
16
- case 'small':
17
- return '2rem';
18
- case 'large':
19
- return '5rem';
20
- default:
21
- return '3rem';
22
- }
23
- });
24
- </script>
25
- <template>
26
- <div class="dashed-container gradient-hover" @click="$emit('click')">
27
- <orio-icon
28
- v-if="icon"
29
- :name="icon"
30
- class="icon-class"
31
- :size="iconSize"
32
- />
33
- <span v-if="text" class="text-class" :size>{{ text }}</span>
34
- </div>
35
- </template>
36
-
37
- <style scoped>
38
- .dashed-container {
39
- cursor: pointer;
40
- border: 3px dashed var(--color-border);
41
- border-radius: 4px;
42
- padding: 0.5rem;
43
- display: flex;
44
- flex-direction: column;
45
- justify-content: center;
46
- align-items: center;
47
- }
48
- .dashed-container:hover .text-class {
49
- color: var(--color-accent-hover);
50
- }
51
-
52
- .icon-class {
53
- color: var(--color-muted);
54
- }
55
-
56
- .text-class {
57
- color: var(--color-accent);
58
- }
59
- </style>
@@ -1,30 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed } from 'vue';
3
- import { nanoid } from 'nanoid';
4
-
5
- interface Props {
6
- month?: boolean;
7
- }
8
- defineProps<Props>();
9
-
10
- const date = defineModel<string | null | undefined>('date', {
11
- required: true,
12
- });
13
-
14
- const randomName = computed(() => `date-${nanoid(8)}`);
15
- </script>
16
-
17
- <template>
18
- <orio-control-element class="date-picker" v-bind="$attrs">
19
- <input
20
- v-model="date"
21
- :type="month ? 'month' : 'date'"
22
- class="date-input"
23
- :name="randomName"
24
- />
25
- </orio-control-element>
26
- </template>
27
-
28
- <style scoped>
29
- .date-picker *{cursor:pointer;width:100%}.date-picker-label{color:var(--color-text);display:inline-flex;flex-direction:column;font-size:.9rem;gap:.25rem}.date-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--color-bg);border:1px solid var(--color-border);border-radius:4px;box-sizing:border-box;color:var(--color-text);font-size:.95rem;padding:.4rem .6rem;transition:border-color .2s ease,box-shadow .2s ease}.date-input:focus,.date-input:hover{border-color:var(--color-accent)}.date-input:focus{box-shadow:0 0 0 2px var(--color-accent-soft);outline:none}.date-input:disabled{background-color:var(--color-surface);color:var(--color-muted);cursor:not-allowed}.date-input::-webkit-calendar-picker-indicator{cursor:pointer;filter:invert(36%) sepia(65%) saturate(325%) hue-rotate(180deg);opacity:.7;-webkit-transition:opacity .2s ease;transition:opacity .2s ease}.date-input::-webkit-calendar-picker-indicator:hover{opacity:1}
30
- </style>
@@ -1,73 +0,0 @@
1
- <script setup lang="ts">
2
- import { ref, watch, computed } from 'vue';
3
- import type { ResumeDate } from './view/Dates.vue';
4
-
5
- export interface DateRangePickerProps {
6
- month?: boolean;
7
- }
8
-
9
- defineProps<DateRangePickerProps>();
10
-
11
- const dates = defineModel<ResumeDate>('dates', { required: true });
12
-
13
- const present = ref(dates.value.endDate !== '' && !dates.value.endDate);
14
-
15
- watch(present, (value) => {
16
- if (value) {
17
- dates.value.endDate = null; // Set end date to null when present is checked
18
- } else {
19
- dates.value.endDate = ''; // Reset end date when present is unchecked
20
- }
21
- });
22
-
23
- const dateIsCorrect = computed(() => {
24
- // Ensure that the start date is before the end date
25
- if (dates.value.startDate && dates.value.endDate) {
26
- return new Date(dates.value.startDate) <= new Date(dates.value.endDate);
27
- }
28
- return true; // If one of the dates is empty, consider it correct
29
- });
30
-
31
- defineExpose({ dateIsCorrect });
32
- </script>
33
-
34
- <template>
35
- <div>
36
- <orio-control-element>
37
- <div class="date-range-picker">
38
- <orio-date-picker v-model:date="dates.startDate" :month />
39
- <orio-date-picker v-model:date="dates.endDate" :month />
40
- <orio-check-box v-model="present"> Present </orio-check-box>
41
- </div>
42
- </orio-control-element>
43
- <div v-if="!dateIsCorrect" class="error-message">
44
- <p>Start date must be before end date.</p>
45
- </div>
46
- </div>
47
- </template>
48
-
49
- <style scoped>
50
- .date-range-picker {
51
- display: flex;
52
- align-items: center;
53
- flex-wrap: wrap;
54
- }
55
- .date-range-picker > * {
56
- min-width: 0;
57
- }
58
- .date-range-picker .date-picker {
59
- margin-inline: 0;
60
- }
61
- .date-range-picker .date-picker:first-child {
62
- margin-inline-end: 0.5rem;
63
- }
64
- .date-range-picker .checkbox {
65
- margin-inline-start: 0.25rem;
66
- }
67
-
68
- .error-message {
69
- color: red;
70
- font-size: 0.875rem;
71
- margin-top: 0.5rem;
72
- }
73
- </style>
@@ -1,81 +0,0 @@
1
- <script setup lang="ts">
2
- interface Props {
3
- icon?: string;
4
- title: string;
5
- description?: string;
6
- size?: 'small' | 'medium' | 'large';
7
- }
8
-
9
- const props = withDefaults(defineProps<Props>(), {
10
- size: 'medium',
11
- });
12
- </script>
13
-
14
- <template>
15
- <div class="empty-state" :class="size">
16
- <orio-icon v-if="icon" :name="icon" class="empty-state-icon" />
17
- <orio-view-text
18
- type="title"
19
- :size="size === 'large' ? 'medium' : 'small'"
20
- class="empty-state-title"
21
- >
22
- {{ title }}
23
- </orio-view-text>
24
- <orio-view-text
25
- v-if="description"
26
- type="subtitle"
27
- class="empty-state-description"
28
- >
29
- {{ description }}
30
- </orio-view-text>
31
- <slot />
32
- </div>
33
- </template>
34
-
35
- <style scoped>
36
- .empty-state {
37
- display: flex;
38
- flex-direction: column;
39
- align-items: center;
40
- justify-content: center;
41
- text-align: center;
42
- gap: 0.5rem;
43
- padding: 2rem;
44
- color: var(--color-text-secondary);
45
- }
46
- .empty-state.small {
47
- padding: 1rem;
48
- gap: 0.25rem;
49
- }
50
- .empty-state.small .empty-state-icon {
51
- font-size: 2rem;
52
- }
53
- .empty-state.medium {
54
- padding: 2rem;
55
- gap: 0.5rem;
56
- }
57
- .empty-state.medium .empty-state-icon {
58
- font-size: 3rem;
59
- }
60
- .empty-state.large {
61
- padding: 3rem;
62
- gap: 1rem;
63
- }
64
- .empty-state.large .empty-state-icon {
65
- font-size: 4rem;
66
- }
67
-
68
- .empty-state-icon {
69
- color: var(--color-text-tertiary);
70
- opacity: 0.5;
71
- }
72
-
73
- .empty-state-title {
74
- color: var(--color-text-secondary);
75
- }
76
-
77
- .empty-state-description {
78
- color: var(--color-text-tertiary);
79
- max-width: 30ch;
80
- }
81
- </style>
@@ -1,40 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed } from 'vue'
3
- import { iconRegistry, type IconName } from '../utils/icon-registry'
4
-
5
- export interface IconProps {
6
- name: IconName | string
7
- size?: string | number
8
- color?: string
9
- }
10
-
11
- const props = withDefaults(defineProps<IconProps>(), {
12
- size: '1em',
13
- color: 'currentColor'
14
- })
15
-
16
- const iconSvg = computed(() => iconRegistry[props.name] || '')
17
- const sizeValue = computed(() =>
18
- typeof props.size === 'number' ? `${props.size}px` : props.size
19
- )
20
- </script>
21
-
22
- <template>
23
- <span
24
- class="orio-icon"
25
- :style="{
26
- width: sizeValue,
27
- height: sizeValue,
28
- color: color,
29
- display: 'inline-flex',
30
- alignItems: 'center',
31
- justifyContent: 'center',
32
- flexShrink: 0
33
- }"
34
- v-html="iconSvg"
35
- />
36
- </template>
37
-
38
- <style scoped>
39
- .orio-icon{align-items:center;display:inline-flex;flex-shrink:0;justify-content:center}.orio-icon :deep(svg){fill:currentColor;height:100%;width:100%}
40
- </style>
@@ -1,48 +0,0 @@
1
- <script setup lang="ts">
2
- defineEmits<{
3
- (e: 'input', value: string): void;
4
- }>();
5
-
6
- const text = defineModel<string>({ default: '' });
7
- </script>
8
-
9
- <template>
10
- <orio-control-element v-bind="$attrs">
11
- <input
12
- v-bind="$attrs"
13
- v-model="text"
14
- type="text"
15
- class="text-input"
16
- >
17
- </orio-control-element>
18
- </template>
19
-
20
- <style scoped>
21
- .text-input {
22
- width: 100%;
23
- padding: 0.5rem 0.75rem;
24
- border: 1px solid var(--color-border);
25
- border-radius: 4px;
26
- font-size: 1rem;
27
- color: var(--color-text);
28
- background-color: var(--color-bg);
29
- box-sizing: border-box;
30
- transition: border-color 0.2s ease, box-shadow 0.2s ease;
31
- }
32
- .text-input::placeholder {
33
- color: var(--color-muted);
34
- }
35
- .text-input:hover {
36
- border-color: var(--color-accent);
37
- }
38
- .text-input:focus {
39
- border-color: var(--color-accent);
40
- box-shadow: 0 0 0 2px var(--color-accent-soft);
41
- outline: none;
42
- }
43
- .text-input:disabled {
44
- background-color: var(--color-surface);
45
- color: var(--color-muted);
46
- cursor: not-allowed;
47
- }
48
- </style>
@@ -1,6 +0,0 @@
1
- <script setup lang="ts">
2
- // Loading spinner using the bundled loading-loop icon
3
- </script>
4
- <template>
5
- <orio-icon name="loading-loop" />
6
- </template>
@@ -1,69 +0,0 @@
1
- <script setup lang="ts">
2
- import { ref, nextTick, watch } from 'vue';
3
- import { useWindowSize, useTimeoutFn } from '@vueuse/core';
4
-
5
- export interface OriginRect {
6
- x: number;
7
- y: number;
8
- width: number;
9
- height: number;
10
- }
11
-
12
- const props = defineProps<{
13
- origin: OriginRect | null;
14
- }>();
15
-
16
- const show = defineModel<Boolean>('show');
17
-
18
- const wrapper = ref<HTMLDivElement | null>(null);
19
-
20
- const { width: windowWidth, height: windowHeight } = useWindowSize();
21
-
22
- function animateToCenter(el: HTMLDivElement) {
23
- useTimeoutFn(() => {
24
- requestAnimationFrame(() => {
25
- el.style.transform = 'translate(0, 0) scale(1)';
26
- el.style.opacity = '1';
27
- });
28
- }, 100);
29
- }
30
-
31
- async function animateOpen() {
32
- await nextTick();
33
-
34
- const el = wrapper.value;
35
- if (!el) return;
36
- if (!props.origin) {
37
- animateToCenter(el);
38
- return;
39
- }
40
-
41
- const { x, y, width, height } = props.origin;
42
-
43
- el.style.transform = `
44
- translate(${x - windowWidth.value / 2}px, ${y - windowHeight.value / 2}px)
45
- scale(${width / el.offsetWidth}, ${height / el.offsetHeight})
46
- `;
47
- el.style.opacity = '0.5';
48
-
49
- animateToCenter(el);
50
- }
51
-
52
- watch(show, (open) => {
53
- if (open) animateOpen();
54
- });
55
- </script>
56
-
57
- <template>
58
- <transition name="overlay-fade">
59
- <div v-if="show" class="overlay" @click.self="show = false">
60
- <div ref="wrapper" class="modal">
61
- <slot />
62
- </div>
63
- </div>
64
- </transition>
65
- </template>
66
-
67
- <style scoped>
68
- .overlay{align-items:center;backdrop-filter:blur(6px);background:rgba(0,0,0,.45);display:flex;inset:0;justify-content:center;position:fixed;transition:opacity .25s ease}.modal{background:#fff;border-radius:1rem;box-shadow:0 25px 60px rgba(0,0,0,.25);color:var(--color-muted);max-height:90vh;max-width:90vw;padding:24px;position:absolute;transform-origin:top left;transition:transform .35s cubic-bezier(.2,.8,.2,1),opacity .3s ease;width:380px}.modal,.overlay-fade-enter-from,.overlay-fade-leave-to{opacity:0}.overlay-fade-enter-active,.overlay-fade-leave-active{transition:opacity .25s ease}
69
- </style>