@paraxe/vue 1.0.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 (107) hide show
  1. package/dist/.loba-build.json +5 -0
  2. package/dist/composites/Accordion.d.ts +22 -0
  3. package/dist/composites/AccordionItem.d.ts +21 -0
  4. package/dist/composites/ButtonGroup.d.ts +21 -0
  5. package/dist/composites/SectionHeader.d.ts +20 -0
  6. package/dist/data/EmptyState.d.ts +22 -0
  7. package/dist/data/List.d.ts +35 -0
  8. package/dist/data/ListItem.d.ts +19 -0
  9. package/dist/data/Pagination.d.ts +17 -0
  10. package/dist/data/Table.d.ts +51 -0
  11. package/dist/elements/Badge.d.ts +19 -0
  12. package/dist/elements/Button.d.ts +33 -0
  13. package/dist/elements/Card.d.ts +21 -0
  14. package/dist/elements/Image.d.ts +13 -0
  15. package/dist/elements/Tag.d.ts +13 -0
  16. package/dist/feedback/Alert.d.ts +27 -0
  17. package/dist/feedback/Progress.d.ts +29 -0
  18. package/dist/feedback/Skeleton.d.ts +13 -0
  19. package/dist/feedback/Toast.d.ts +33 -0
  20. package/dist/forms/Checkbox.d.ts +27 -0
  21. package/dist/forms/Choice.d.ts +19 -0
  22. package/dist/forms/ChoiceGroup.d.ts +32 -0
  23. package/dist/forms/FormField.d.ts +29 -0
  24. package/dist/forms/Input.d.ts +29 -0
  25. package/dist/forms/Radio.d.ts +26 -0
  26. package/dist/forms/Select.d.ts +28 -0
  27. package/dist/forms/Switch.d.ts +24 -0
  28. package/dist/forms/Textarea.d.ts +24 -0
  29. package/dist/index.d.ts +47 -0
  30. package/dist/index.js +1888 -0
  31. package/dist/navigation/Breadcrumb.d.ts +22 -0
  32. package/dist/navigation/Breadcrumbs.d.ts +18 -0
  33. package/dist/navigation/Sidebar.d.ts +22 -0
  34. package/dist/navigation/SidebarGroup.d.ts +18 -0
  35. package/dist/navigation/SidebarItem.d.ts +28 -0
  36. package/dist/navigation/Tab.d.ts +19 -0
  37. package/dist/navigation/Tabs.d.ts +22 -0
  38. package/dist/overlays/Dialog.d.ts +26 -0
  39. package/dist/overlays/Drawer.d.ts +28 -0
  40. package/dist/overlays/Popover.d.ts +20 -0
  41. package/dist/overlays/Tooltip.d.ts +21 -0
  42. package/dist/primitives/Container.d.ts +19 -0
  43. package/dist/primitives/Divider.d.ts +3 -0
  44. package/dist/primitives/Grid.d.ts +25 -0
  45. package/dist/primitives/Section.d.ts +13 -0
  46. package/dist/primitives/Stack.d.ts +21 -0
  47. package/dist/typography/Eyebrow.d.ts +13 -0
  48. package/dist/typography/Heading.d.ts +19 -0
  49. package/dist/typography/Label.d.ts +24 -0
  50. package/dist/typography/Text.d.ts +22 -0
  51. package/doc.md +527 -0
  52. package/package.json +29 -0
  53. package/src/composites/Accordion.vue +60 -0
  54. package/src/composites/AccordionItem.vue +66 -0
  55. package/src/composites/ButtonGroup.vue +27 -0
  56. package/src/composites/SectionHeader.vue +23 -0
  57. package/src/data/EmptyState.vue +40 -0
  58. package/src/data/List.vue +125 -0
  59. package/src/data/ListItem.vue +97 -0
  60. package/src/data/Pagination.vue +254 -0
  61. package/src/data/Table.vue +382 -0
  62. package/src/elements/Avatar.vue +0 -0
  63. package/src/elements/Badge.vue +30 -0
  64. package/src/elements/Button.vue +56 -0
  65. package/src/elements/Card.vue +34 -0
  66. package/src/elements/Icon.vue +0 -0
  67. package/src/elements/Image.vue +36 -0
  68. package/src/elements/Tag.vue +10 -0
  69. package/src/env.d.ts +8 -0
  70. package/src/feedback/Alert.vue +63 -0
  71. package/src/feedback/Progress.vue +95 -0
  72. package/src/feedback/Skeleton.vue +43 -0
  73. package/src/feedback/Toast.vue +141 -0
  74. package/src/forms/Checkbox.vue +54 -0
  75. package/src/forms/Choice.vue +82 -0
  76. package/src/forms/ChoiceGroup.vue +130 -0
  77. package/src/forms/FormField.vue +55 -0
  78. package/src/forms/Input.vue +54 -0
  79. package/src/forms/Radio.vue +64 -0
  80. package/src/forms/Select.vue +43 -0
  81. package/src/forms/Switch.vue +57 -0
  82. package/src/forms/Textarea.vue +54 -0
  83. package/src/index.ts +47 -0
  84. package/src/navigation/Breadcrumb.vue +59 -0
  85. package/src/navigation/Breadcrumbs.vue +30 -0
  86. package/src/navigation/Menu.vue +0 -0
  87. package/src/navigation/Sidebar.vue +35 -0
  88. package/src/navigation/SidebarGroup.vue +34 -0
  89. package/src/navigation/SidebarItem.vue +137 -0
  90. package/src/navigation/Tab.vue +78 -0
  91. package/src/navigation/Tabs.vue +68 -0
  92. package/src/overlays/Dialog.vue +193 -0
  93. package/src/overlays/Drawer.vue +200 -0
  94. package/src/overlays/Popover.vue +106 -0
  95. package/src/overlays/Tooltip.vue +69 -0
  96. package/src/primitives/Container.vue +24 -0
  97. package/src/primitives/Divider.vue +6 -0
  98. package/src/primitives/Grid.vue +36 -0
  99. package/src/primitives/Section.vue +8 -0
  100. package/src/primitives/Stack.vue +28 -0
  101. package/src/typography/Eyebrow.vue +9 -0
  102. package/src/typography/Heading.vue +27 -0
  103. package/src/typography/Label.vue +34 -0
  104. package/src/typography/Text.vue +38 -0
  105. package/tsconfig.json +17 -0
  106. package/tsconfig.tsbuildinfo +1 -0
  107. package/vite.config.ts +30 -0
@@ -0,0 +1,40 @@
1
+ <script setup lang="ts">
2
+ import { computed } from "vue";
3
+
4
+ export interface Props {
5
+ as?: string;
6
+ }
7
+
8
+ const props = withDefaults(defineProps<Props>(), {
9
+ as: "div",
10
+ });
11
+
12
+ const classes = computed(() => [
13
+ "empty-state",
14
+ ]);
15
+ </script>
16
+
17
+ <template>
18
+ <component
19
+ :is="props.as"
20
+ :class="classes"
21
+ >
22
+ <div
23
+ v-if="$slots.icon"
24
+ class="empty-state-icon"
25
+ >
26
+ <slot name="icon" />
27
+ </div>
28
+
29
+ <div class="empty-state-content">
30
+ <slot />
31
+ </div>
32
+
33
+ <div
34
+ v-if="$slots.actions"
35
+ class="empty-state-actions"
36
+ >
37
+ <slot name="actions" />
38
+ </div>
39
+ </component>
40
+ </template>
@@ -0,0 +1,125 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ provide,
4
+ ref,
5
+ watch,
6
+ } from "vue";
7
+
8
+ export interface ListProps {
9
+ selectable?: boolean;
10
+ multiple?: boolean;
11
+ }
12
+
13
+ export interface ListContext {
14
+ selectable: boolean;
15
+ multiple: boolean;
16
+
17
+
18
+ isSelected: (
19
+ value: string | number
20
+ ) => boolean;
21
+
22
+ toggleSelection: (
23
+ value: string | number
24
+ ) => void;
25
+ }
26
+
27
+ const props = withDefaults(
28
+ defineProps<ListProps>(),
29
+ {
30
+ selectable: false,
31
+ multiple: false,
32
+ },
33
+ );
34
+
35
+ const selectedValues = ref<
36
+ Set<string | number>
37
+ >(new Set());
38
+
39
+ const emit = defineEmits<{
40
+ "update:modelValue": [
41
+ value:
42
+ | string
43
+ | number
44
+ | Array<string | number>
45
+ | null,
46
+ ];
47
+ }>();
48
+
49
+ const modelValue = defineModel<
50
+ string | number | Array<string | number> | null
51
+ >({
52
+ default: null,
53
+ });
54
+
55
+ watch(
56
+ modelValue,
57
+ (value) => {
58
+ if (value === null || value === undefined) {
59
+ selectedValues.value = new Set();
60
+ return;
61
+ }
62
+
63
+ selectedValues.value = new Set(
64
+ Array.isArray(value)
65
+ ? value
66
+ : [value],
67
+ );
68
+ },
69
+ { immediate: true },
70
+ );
71
+
72
+ function isSelected(
73
+ value: string | number,
74
+ ) {
75
+ return selectedValues.value.has(value);
76
+ }
77
+
78
+ function toggleSelection(
79
+ value: string | number,
80
+ ) {
81
+ if (!props.selectable) {
82
+ return;
83
+ }
84
+
85
+ const next = new Set(
86
+ selectedValues.value,
87
+ );
88
+
89
+ if (props.multiple) {
90
+ if (next.has(value)) {
91
+ next.delete(value);
92
+ } else {
93
+ next.add(value);
94
+ }
95
+ } else {
96
+ if (next.has(value)) {
97
+ next.clear();
98
+ } else {
99
+ next.clear();
100
+ next.add(value);
101
+ }
102
+ }
103
+
104
+ selectedValues.value = next;
105
+
106
+ const values = [...next];
107
+
108
+ modelValue.value = props.multiple
109
+ ? values
110
+ : (values[0] ?? null);
111
+ }
112
+
113
+ provide<ListContext>("loba-list", {
114
+ selectable: props.selectable,
115
+ multiple: props.multiple,
116
+ isSelected,
117
+ toggleSelection,
118
+ });
119
+ </script>
120
+
121
+ <template>
122
+ <div class="list">
123
+ <slot />
124
+ </div>
125
+ </template>
@@ -0,0 +1,97 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ computed,
4
+ inject,
5
+ } from "vue";
6
+
7
+ export interface ListItemProps {
8
+ value: string | number;
9
+ disabled?: boolean;
10
+ }
11
+
12
+ const props = withDefaults(
13
+ defineProps<ListItemProps>(),
14
+ {
15
+ disabled: false,
16
+ },
17
+ );
18
+
19
+ interface ListContext {
20
+ selectable: boolean;
21
+ multiple: boolean;
22
+
23
+ isSelected: (
24
+ value: string | number
25
+ ) => boolean;
26
+
27
+ toggleSelection: (
28
+ value: string | number
29
+ ) => void;
30
+ }
31
+
32
+ const injectedList = inject<ListContext>("loba-list");
33
+
34
+ if (!injectedList) {
35
+ throw new Error(
36
+ "ListItem must be used inside a List.",
37
+ );
38
+ }
39
+
40
+ const list = injectedList;
41
+
42
+ if (!list) {
43
+ throw new Error(
44
+ "ListItem must be used inside a List.",
45
+ );
46
+ }
47
+
48
+ const isSelected = computed(() =>
49
+ list.isSelected(props.value),
50
+ );
51
+
52
+ const classes = computed(() => ({
53
+ "list-item": true,
54
+ "list-item--selectable":
55
+ list.selectable && !props.disabled,
56
+ "list-item--selected":
57
+ isSelected.value,
58
+ "list-item--disabled":
59
+ props.disabled,
60
+ }));
61
+
62
+ function handleClick() {
63
+ if (
64
+ props.disabled ||
65
+ !list.selectable
66
+ ) {
67
+ return;
68
+ }
69
+
70
+ list.toggleSelection(props.value);
71
+ }
72
+ </script>
73
+
74
+ <template>
75
+ <div
76
+ :class="classes"
77
+ :tabindex="
78
+ list.selectable && !props.disabled
79
+ ? 0
80
+ : undefined
81
+ "
82
+ :aria-selected="
83
+ list.selectable
84
+ ? isSelected
85
+ : undefined
86
+ "
87
+ :aria-disabled="
88
+ props.disabled || undefined
89
+ "
90
+ role="listitem"
91
+ @click="handleClick"
92
+ @keydown.enter="handleClick"
93
+ @keydown.space.prevent="handleClick"
94
+ >
95
+ <slot />
96
+ </div>
97
+ </template>
@@ -0,0 +1,254 @@
1
+ <script setup lang="ts">
2
+ import { computed } from "vue";
3
+
4
+ export interface PaginationProps {
5
+ currentPage: number;
6
+ totalItems: number;
7
+ pageSize: number;
8
+ siblingCount?: number;
9
+ compact?: boolean;
10
+ }
11
+
12
+ const props = withDefaults(
13
+ defineProps<PaginationProps>(),
14
+ {
15
+ siblingCount: 1,
16
+ compact: false,
17
+ },
18
+ );
19
+
20
+ const emit = defineEmits<{
21
+ "update:currentPage": [
22
+ page: number,
23
+ ];
24
+ }>();
25
+
26
+ const totalPages = computed(() =>
27
+ Math.max(
28
+ 1,
29
+ Math.ceil(
30
+ props.totalItems / props.pageSize,
31
+ ),
32
+ ),
33
+ );
34
+
35
+ const safeCurrentPage = computed(() =>
36
+ Math.min(
37
+ Math.max(props.currentPage, 1),
38
+ totalPages.value,
39
+ ),
40
+ );
41
+
42
+ type PaginationItem =
43
+ | number
44
+ | "...";
45
+
46
+ const pages = computed<PaginationItem[]>(() => {
47
+ const total = totalPages.value;
48
+ const current = safeCurrentPage.value;
49
+ const siblings = Math.max(
50
+ 0,
51
+ props.siblingCount,
52
+ );
53
+
54
+ if (total <= 7) {
55
+ return Array.from(
56
+ { length: total },
57
+ (_, index) => index + 1,
58
+ );
59
+ }
60
+
61
+ const left = Math.max(
62
+ current - siblings,
63
+ 1,
64
+ );
65
+
66
+ const right = Math.min(
67
+ current + siblings,
68
+ total,
69
+ );
70
+
71
+ const showLeftDots = left > 2;
72
+ const showRightDots =
73
+ right < total - 1;
74
+
75
+ const result: PaginationItem[] = [1];
76
+
77
+ if (showLeftDots) {
78
+ result.push("...");
79
+ }
80
+
81
+ const start = showLeftDots
82
+ ? left
83
+ : 2;
84
+
85
+ const end = showRightDots
86
+ ? right
87
+ : total - 1;
88
+
89
+ for (
90
+ let page = start;
91
+ page <= end;
92
+ page++
93
+ ) {
94
+ result.push(page);
95
+ }
96
+
97
+ if (showRightDots) {
98
+ result.push("...");
99
+ }
100
+
101
+ result.push(total);
102
+
103
+ return result;
104
+ });
105
+
106
+ const classes = computed(() => ({
107
+ pagination: true,
108
+ "pagination-compact":
109
+ props.compact,
110
+ }));
111
+
112
+ function goTo(page: number) {
113
+ const next = Math.min(
114
+ Math.max(page, 1),
115
+ totalPages.value,
116
+ );
117
+
118
+ if (
119
+ next === safeCurrentPage.value
120
+ ) {
121
+ return;
122
+ }
123
+
124
+ emit(
125
+ "update:currentPage",
126
+ next,
127
+ );
128
+ }
129
+
130
+ function goPrevious() {
131
+ goTo(safeCurrentPage.value - 1);
132
+ }
133
+
134
+ function goNext() {
135
+ goTo(safeCurrentPage.value + 1);
136
+ }
137
+
138
+ function goFirst() {
139
+ goTo(1);
140
+ }
141
+
142
+ function goLast() {
143
+ goTo(totalPages.value);
144
+ }
145
+ </script>
146
+
147
+ <template>
148
+ <nav
149
+ :class="classes"
150
+ aria-label="Pagination"
151
+ >
152
+ <div class="pagination-controls">
153
+ <button
154
+ class="pagination-item"
155
+ type="button"
156
+ :disabled="
157
+ safeCurrentPage === 1
158
+ "
159
+ :class="{
160
+ 'pagination-item--disabled':
161
+ safeCurrentPage === 1,
162
+ }"
163
+ aria-label="First page"
164
+ @click="goFirst"
165
+ >
166
+ «
167
+ </button>
168
+
169
+ <button
170
+ class="pagination-item"
171
+ type="button"
172
+ :disabled="
173
+ safeCurrentPage === 1
174
+ "
175
+ :class="{
176
+ 'pagination-item--disabled':
177
+ safeCurrentPage === 1,
178
+ }"
179
+ aria-label="Previous page"
180
+ @click="goPrevious"
181
+ >
182
+
183
+ </button>
184
+ </div>
185
+
186
+ <div class="pagination-pages">
187
+ <template
188
+ v-for="(item, index) in pages"
189
+ :key="`${item}-${index}`"
190
+ >
191
+ <span
192
+ v-if="item === '...'"
193
+ class="pagination-ellipsis"
194
+ >
195
+
196
+ </span>
197
+
198
+ <button
199
+ v-else
200
+ class="pagination-item"
201
+ type="button"
202
+ :class="{
203
+ 'pagination-item--current':
204
+ item === safeCurrentPage,
205
+ }"
206
+ :aria-current="
207
+ item === safeCurrentPage
208
+ ? 'page'
209
+ : undefined
210
+ "
211
+ @click="goTo(item)"
212
+ >
213
+ {{ item }}
214
+ </button>
215
+ </template>
216
+ </div>
217
+
218
+ <div class="pagination-controls">
219
+ <button
220
+ class="pagination-item"
221
+ type="button"
222
+ :disabled="
223
+ safeCurrentPage === totalPages
224
+ "
225
+ :class="{
226
+ 'pagination-item--disabled':
227
+ safeCurrentPage ===
228
+ totalPages,
229
+ }"
230
+ aria-label="Next page"
231
+ @click="goNext"
232
+ >
233
+
234
+ </button>
235
+
236
+ <button
237
+ class="pagination-item"
238
+ type="button"
239
+ :disabled="
240
+ safeCurrentPage === totalPages
241
+ "
242
+ :class="{
243
+ 'pagination-item--disabled':
244
+ safeCurrentPage ===
245
+ totalPages,
246
+ }"
247
+ aria-label="Last page"
248
+ @click="goLast"
249
+ >
250
+ »
251
+ </button>
252
+ </div>
253
+ </nav>
254
+ </template>