@witchcraft/ui 0.1.1 → 0.1.3

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 (122) hide show
  1. package/dist/module.cjs +5 -0
  2. package/dist/module.d.ts +36 -0
  3. package/dist/module.json +2 -2
  4. package/dist/module.mjs +2 -1
  5. package/dist/runtime/assets/utils.css +1 -1
  6. package/dist/runtime/components/Aria/Aria.vue +9 -5
  7. package/dist/runtime/components/Focus.stories.d.ts +11 -0
  8. package/dist/runtime/components/Focus.stories.js +53 -0
  9. package/dist/runtime/components/Icon/Icon.vue +30 -10
  10. package/dist/runtime/components/LibButton/LibButton.stories.d.ts +12 -0
  11. package/dist/runtime/components/LibButton/LibButton.stories.js +94 -0
  12. package/dist/runtime/components/LibButton/LibButton.vue +72 -58
  13. package/dist/runtime/components/LibCheckbox/LibCheckbox.stories.d.ts +14 -0
  14. package/dist/runtime/components/LibCheckbox/LibCheckbox.stories.js +29 -0
  15. package/dist/runtime/components/LibCheckbox/LibCheckbox.vue +74 -48
  16. package/dist/runtime/components/LibColorInput/LibColorInput.stories.d.ts +7 -0
  17. package/dist/runtime/components/LibColorInput/LibColorInput.stories.js +58 -0
  18. package/dist/runtime/components/LibColorInput/LibColorInput.vue +107 -63
  19. package/dist/runtime/components/LibColorPicker/LibColorPicker.stories.d.ts +9 -0
  20. package/dist/runtime/components/LibColorPicker/LibColorPicker.stories.js +68 -0
  21. package/dist/runtime/components/LibColorPicker/LibColorPicker.vue +352 -271
  22. package/dist/runtime/components/LibDarkModeSwitcher/LibDarkModeSwitcher.stories.d.ts +7 -0
  23. package/dist/runtime/components/LibDarkModeSwitcher/LibDarkModeSwitcher.stories.js +36 -0
  24. package/dist/runtime/components/LibDarkModeSwitcher/LibDarkModeSwitcher.vue +56 -32
  25. package/dist/runtime/components/LibDatePicker/LibDatePicker.stories.d.ts +11 -0
  26. package/dist/runtime/components/LibDatePicker/LibDatePicker.stories.js +98 -0
  27. package/dist/runtime/components/LibDatePicker/LibDatePicker.vue +38 -17
  28. package/dist/runtime/components/LibDatePicker/LibRangeDatePicker.vue +82 -53
  29. package/dist/runtime/components/LibDatePicker/LibSingleDatePicker.vue +67 -50
  30. package/dist/runtime/components/LibDatePicker/LibTimeZonePicker.vue +8 -7
  31. package/dist/runtime/components/LibDebug/LibDebug.stories.d.ts +9 -0
  32. package/dist/runtime/components/LibDebug/LibDebug.stories.js +46 -0
  33. package/dist/runtime/components/LibDebug/LibDebug.vue +70 -42
  34. package/dist/runtime/components/LibDevOnly/LibDevOnly.vue +31 -18
  35. package/dist/runtime/components/LibFileInput/LibFileInput.stories.d.ts +10 -0
  36. package/dist/runtime/components/LibFileInput/LibFileInput.stories.js +63 -0
  37. package/dist/runtime/components/LibFileInput/LibFileInput.vue +156 -113
  38. package/dist/runtime/components/LibInputDeprecated/LibInputDeprecated.stories.d.ts +33 -0
  39. package/dist/runtime/components/LibInputDeprecated/LibInputDeprecated.stories.js +384 -0
  40. package/dist/runtime/components/LibInputDeprecated/LibInputDeprecated.vue +241 -215
  41. package/dist/runtime/components/LibLabel/LibLabel.stories.d.ts +6 -0
  42. package/dist/runtime/components/LibLabel/LibLabel.stories.js +25 -0
  43. package/dist/runtime/components/LibLabel/LibLabel.vue +46 -30
  44. package/dist/runtime/components/LibMultiValues/LibMultiValues.stories.d.ts +23 -0
  45. package/dist/runtime/components/LibMultiValues/LibMultiValues.stories.js +61 -0
  46. package/dist/runtime/components/LibMultiValues/LibMultiValues.vue +58 -44
  47. package/dist/runtime/components/LibNotifications/LibNotification.stories.d.ts +15 -0
  48. package/dist/runtime/components/LibNotifications/LibNotification.stories.js +126 -0
  49. package/dist/runtime/components/LibNotifications/LibNotification.vue +48 -32
  50. package/dist/runtime/components/LibNotifications/LibNotifications.stories.d.ts +6 -0
  51. package/dist/runtime/components/LibNotifications/LibNotifications.stories.js +109 -0
  52. package/dist/runtime/components/LibNotifications/LibNotifications.vue +83 -63
  53. package/dist/runtime/components/LibPagination/LibPagination.stories.d.ts +6 -0
  54. package/dist/runtime/components/LibPagination/LibPagination.stories.js +40 -0
  55. package/dist/runtime/components/LibPagination/LibPagination.vue +111 -67
  56. package/dist/runtime/components/LibPalette/LibPalette.stories.d.ts +6 -0
  57. package/dist/runtime/components/LibPalette/LibPalette.stories.js +20 -0
  58. package/dist/runtime/components/LibPalette/LibPalette.vue +23 -20
  59. package/dist/runtime/components/LibPopup/LibPopup.stories.d.ts +14 -0
  60. package/dist/runtime/components/LibPopup/LibPopup.stories.js +147 -0
  61. package/dist/runtime/components/LibPopup/LibPopup.vue +351 -314
  62. package/dist/runtime/components/LibProgressBar/LibProgressBar.stories.d.ts +10 -0
  63. package/dist/runtime/components/LibProgressBar/LibProgressBar.stories.js +81 -0
  64. package/dist/runtime/components/LibProgressBar/LibProgressBar.vue +91 -70
  65. package/dist/runtime/components/LibRecorder/LibRecorder.stories.d.ts +19 -0
  66. package/dist/runtime/components/LibRecorder/LibRecorder.stories.js +63 -0
  67. package/dist/runtime/components/LibRecorder/LibRecorder.vue +177 -133
  68. package/dist/runtime/components/LibRoot/LibRoot.vue +100 -73
  69. package/dist/runtime/components/LibSimpleInput/LibSimpleInput.stories.d.ts +26 -0
  70. package/dist/runtime/components/LibSimpleInput/LibSimpleInput.stories.js +78 -0
  71. package/dist/runtime/components/LibSimpleInput/LibSimpleInput.vue +77 -49
  72. package/dist/runtime/components/LibSuggestions/LibSuggestions.stories.d.ts +27 -0
  73. package/dist/runtime/components/LibSuggestions/LibSuggestions.stories.js +112 -0
  74. package/dist/runtime/components/LibSuggestions/LibSuggestions.vue +156 -123
  75. package/dist/runtime/components/LibTable/LibTable.stories.d.ts +16 -0
  76. package/dist/runtime/components/LibTable/LibTable.stories.js +156 -0
  77. package/dist/runtime/components/LibTable/LibTable.vue +99 -63
  78. package/dist/runtime/components/Reset.stories.d.ts +5 -0
  79. package/dist/runtime/components/Reset.stories.js +19 -0
  80. package/dist/runtime/components/Scrolling.stories.d.ts +6 -0
  81. package/dist/runtime/components/Scrolling.stories.js +44 -0
  82. package/dist/runtime/components/Template/NAME.vue +36 -15
  83. package/dist/runtime/components/TestControls/TestControls.vue +9 -6
  84. package/dist/runtime/composables/useScrollNearContainerEdges.stories.d.ts +7 -0
  85. package/dist/runtime/composables/useScrollNearContainerEdges.stories.js +85 -0
  86. package/dist/types.d.mts +6 -2
  87. package/dist/types.d.ts +7 -0
  88. package/package.json +11 -5
  89. package/src/module.ts +2 -1
  90. package/src/runtime/assets/utils.css +5 -5
  91. package/src/runtime/components/LibButton/LibButton.vue +2 -6
  92. package/src/runtime/nuxt/plugins/vue-plugin.ts +1 -1
  93. package/dist/runtime/components/Aria/Aria.vue.d.ts +0 -5
  94. package/dist/runtime/components/Icon/Icon.vue.d.ts +0 -21
  95. package/dist/runtime/components/LibButton/LibButton.vue.d.ts +0 -36
  96. package/dist/runtime/components/LibCheckbox/LibCheckbox.vue.d.ts +0 -42
  97. package/dist/runtime/components/LibColorInput/LibColorInput.vue.d.ts +0 -63
  98. package/dist/runtime/components/LibColorPicker/LibColorPicker.vue.d.ts +0 -61
  99. package/dist/runtime/components/LibDarkModeSwitcher/LibDarkModeSwitcher.vue.d.ts +0 -22
  100. package/dist/runtime/components/LibDatePicker/LibDatePicker.vue.d.ts +0 -40
  101. package/dist/runtime/components/LibDatePicker/LibRangeDatePicker.vue.d.ts +0 -34
  102. package/dist/runtime/components/LibDatePicker/LibSingleDatePicker.vue.d.ts +0 -34
  103. package/dist/runtime/components/LibDatePicker/LibTimeZonePicker.vue.d.ts +0 -22
  104. package/dist/runtime/components/LibDebug/LibDebug.vue.d.ts +0 -32
  105. package/dist/runtime/components/LibDevOnly/LibDevOnly.vue.d.ts +0 -22
  106. package/dist/runtime/components/LibFileInput/LibFileInput.vue.d.ts +0 -43
  107. package/dist/runtime/components/LibInputDeprecated/LibInputDeprecated.vue.d.ts +0 -165
  108. package/dist/runtime/components/LibLabel/LibLabel.vue.d.ts +0 -27
  109. package/dist/runtime/components/LibMultiValues/LibMultiValues.vue.d.ts +0 -29
  110. package/dist/runtime/components/LibNotifications/LibNotification.vue.d.ts +0 -17
  111. package/dist/runtime/components/LibNotifications/LibNotifications.vue.d.ts +0 -13
  112. package/dist/runtime/components/LibPagination/LibPagination.vue.d.ts +0 -104
  113. package/dist/runtime/components/LibPalette/LibPalette.vue.d.ts +0 -14
  114. package/dist/runtime/components/LibPopup/LibPopup.vue.d.ts +0 -46
  115. package/dist/runtime/components/LibProgressBar/LibProgressBar.vue.d.ts +0 -41
  116. package/dist/runtime/components/LibRecorder/LibRecorder.vue.d.ts +0 -77
  117. package/dist/runtime/components/LibRoot/LibRoot.vue.d.ts +0 -41
  118. package/dist/runtime/components/LibSimpleInput/LibSimpleInput.vue.d.ts +0 -35
  119. package/dist/runtime/components/LibSuggestions/LibSuggestions.vue.d.ts +0 -94
  120. package/dist/runtime/components/LibTable/LibTable.vue.d.ts +0 -45
  121. package/dist/runtime/components/Template/NAME.vue.d.ts +0 -17
  122. package/dist/runtime/components/TestControls/TestControls.vue.d.ts +0 -5
@@ -0,0 +1,109 @@
1
+ import { reactive, ref } from "vue";
2
+ import LibNotifications from "./LibNotifications.vue";
3
+ import { NotificationHandler } from "../../helpers/NotificationHandler.js";
4
+ import * as components from "../index.js";
5
+ const meta = {
6
+ component: LibNotifications,
7
+ title: "Components/Notifications",
8
+ args: {
9
+ // @ts-expect-error story only arg
10
+ withTitle: true
11
+ }
12
+ };
13
+ export default meta;
14
+ export const Primary = {
15
+ render: (args) => ({
16
+ components,
17
+ setup() {
18
+ const handler = reactive(new NotificationHandler());
19
+ let count = 0;
20
+ const withTitle = ref(args.withTitle);
21
+ const disableTimeout = ref(false);
22
+ const notifyRequiresAction = () => {
23
+ count++;
24
+ void handler.notify({
25
+ title: withTitle.value ? `Notification(${count})` : void 0,
26
+ message: `This is a notification that requires action. Pick an option:`,
27
+ requiresAction: true,
28
+ options: ["Ok", "Default Answer", "Cancel"],
29
+ default: "Default Answer"
30
+ });
31
+ };
32
+ const notifyWithDangerousOption = () => {
33
+ count++;
34
+ void handler.notify({
35
+ title: withTitle.value ? `Notification(${count})` : void 0,
36
+ message: `This is a notification that has a dangerous option. Pick an option:`,
37
+ options: ["Ok", "Default Answer", "Dangerous Option", "Cancel"],
38
+ default: "Default Answer",
39
+ dangerous: ["Dangerous Option"]
40
+ });
41
+ };
42
+ const notifyNonCancellable = () => {
43
+ count++;
44
+ void handler.notify({
45
+ title: withTitle.value ? `Notification(${count})` : void 0,
46
+ message: `This is a non-cancellable notification. Pick an option:`,
47
+ options: ["Ok", "Default Answer"],
48
+ default: "Default Answer",
49
+ cancellable: false
50
+ });
51
+ };
52
+ const notifyNonCancellableRequiresAction = () => {
53
+ count++;
54
+ void handler.notify({
55
+ title: withTitle.value ? `Notification(${count})` : void 0,
56
+ message: `This is a non-cancellable notification. Pick an option:`,
57
+ requiresAction: true,
58
+ options: ["Ok", "Default Answer"],
59
+ default: "Default Answer",
60
+ cancellable: false
61
+ });
62
+ };
63
+ const notifyTimeoutable = () => {
64
+ count++;
65
+ void handler.notify({
66
+ title: withTitle.value ? `Notification(${count})` : void 0,
67
+ message: `This is a notification. No action required.`,
68
+ timeout: disableTimeout.value ? false : 2e3
69
+ });
70
+ };
71
+ return {
72
+ notifyRequiresAction,
73
+ notifyTimeoutable,
74
+ notifyNonCancellable,
75
+ notifyWithDangerousOption,
76
+ notifyNonCancellableRequiresAction,
77
+ handler,
78
+ withTitle,
79
+ disableTimeout,
80
+ args: {
81
+ outline: false,
82
+ ...args
83
+ }
84
+ };
85
+ },
86
+ backgrounds: { disable: true },
87
+ // <lib-debug>{{args.handler}}</lib-debug>
88
+ template: `
89
+ <lib-root :outline="args.outline">
90
+ <lib-button :label="'Notify Timeoutable'" @click="notifyTimeoutable()"></lib-button>
91
+ <lib-button :label="'Notify RequiresAction'" @click="notifyRequiresAction()"></lib-button>
92
+ <lib-button :label="'Notify Non-Cancellable that RequiresAction'" @click="notifyNonCancellableRequiresAction()"></lib-button>
93
+ <lib-button :label="'Notify With Dangerous Option'" @click="notifyWithDangerousOption()"></lib-button>
94
+ <lib-button :label="'Notify Non-Cancellable'" @click="notifyNonCancellable()"></lib-button>
95
+ <input type="checkbox" v-model="withTitle"/> With Title
96
+ <input type="checkbox" v-model="disableTimeout"/> Disable Timeout
97
+ <lib-notifications :handler="handler" />
98
+ History:
99
+ <lib-debug>
100
+ <template v-for="entry in handler.history">
101
+ Message: {{entry.message}}
102
+ Resolution: {{entry.resolution}}
103
+ <br>
104
+ </template>
105
+ </lib-debug>
106
+ </lib-root>
107
+ `
108
+ })
109
+ };
@@ -10,8 +10,8 @@
10
10
  pointer-events-none
11
11
  overflow-hidden
12
12
  flex flex-col
13
- `, $attrs.class)"
14
- v-bind="{ ...$attrs, class: void 0 }"
13
+ `, ($attrs as any).class)"
14
+ v-bind="{ ...$attrs, class: undefined }"
15
15
  >
16
16
  <lib-notification class="pointer-events-auto"
17
17
  :handler="handler"
@@ -24,7 +24,7 @@
24
24
  <Transition>
25
25
  <div
26
26
  v-show="topNotifications.length > 0"
27
- :class="twMerge(`notifications--none`, $attrs.class)"
27
+ :class="twMerge(`notifications--none`, ($attrs as any).class)"
28
28
  />
29
29
  </Transition>
30
30
  <Transition>
@@ -35,7 +35,7 @@
35
35
  p-0
36
36
  backdrop:bg-black/50
37
37
  backdrop:p-5
38
- `, $attrs.class)"
38
+ `, ($attrs as any).class)"
39
39
  ref="dialogEl"
40
40
  @click.self.prevent="topNotifications[0] && NotificationHandler.dismiss(topNotifications[0])"
41
41
  >
@@ -50,72 +50,92 @@
50
50
  </dialog>
51
51
  </Transition>
52
52
  </template>
53
+ <script setup lang="ts">
54
+ import { removeIfIn } from "@alanscodelog/utils/removeIfIn.js"
55
+ import { type HTMLAttributes,nextTick, onBeforeUnmount, ref,shallowReactive, Transition, TransitionGroup } from "vue"
56
+
57
+ import LibNotification from "./LibNotification.vue"
58
+
59
+ import { useNotificationHandler } from "../../composables/useNotificationHandler.js"
60
+ import { type NotificationEntry, NotificationHandler } from "../../helpers/NotificationHandler.js"
61
+ import { twMerge } from "../../utils/twMerge.js"
62
+ import type { LinkableByIdProps, TailwindClassProp } from "../shared/props.js"
53
63
 
54
- <script setup>
55
- import { removeIfIn } from "@alanscodelog/utils/removeIfIn.js";
56
- import { nextTick, onBeforeUnmount, ref, shallowReactive, Transition, TransitionGroup } from "vue";
57
- import LibNotification from "./LibNotification.vue";
58
- import { useNotificationHandler } from "../../composables/useNotificationHandler.js";
59
- import { NotificationHandler } from "../../helpers/NotificationHandler.js";
60
- import { twMerge } from "../../utils/twMerge.js";
61
64
  defineOptions({
62
- name: "lib-notifications",
63
- inheritAttrs: false
64
- });
65
- const props = defineProps({
66
- id: { type: String, required: false },
67
- handler: { type: Object, required: false }
68
- });
69
- const dialogEl = ref(null);
70
- const isOpen = ref(false);
71
- const notifications = shallowReactive([]);
72
- const topNotifications = shallowReactive([]);
65
+ name: "lib-notifications",
66
+ inheritAttrs: false,
67
+ })
68
+
69
+
70
+ const props = defineProps<Props>()
71
+
72
+ const dialogEl = ref<HTMLDialogElement | null>(null)
73
+
74
+ const isOpen = ref(false)
75
+ const notifications = shallowReactive<NotificationEntry[]>([])
76
+ const topNotifications = shallowReactive<NotificationEntry[]>([])
73
77
  const open = () => {
74
- if (!isOpen.value) {
75
- void nextTick(() => {
76
- dialogEl.value.showModal();
77
- isOpen.value = true;
78
- });
79
- }
80
- };
78
+ if (!isOpen.value) {
79
+ void nextTick(() => {
80
+ dialogEl.value!.showModal()
81
+ isOpen.value = true
82
+ })
83
+ }
84
+ }
81
85
  const close = () => {
82
- if (isOpen.value && topNotifications.length === 0) {
83
- dialogEl.value.close();
84
- isOpen.value = false;
85
- }
86
- };
87
- const addNotification = (entry) => {
88
- if (entry.resolution === void 0) {
89
- if (entry.requiresAction) {
90
- topNotifications.push(entry);
91
- open();
92
- entry.promise.then(() => {
93
- removeIfIn(topNotifications, entry);
94
- close();
95
- });
96
- } else {
97
- notifications.splice(0, 0, entry);
98
- entry.promise.then(() => {
99
- removeIfIn(notifications, entry);
100
- });
101
- }
102
- }
103
- };
104
- const notificationListener = (entry, type) => {
105
- if (type === "added") {
106
- addNotification(entry);
107
- }
108
- };
109
- const handler = props.handler ?? useNotificationHandler();
110
- handler.addNotificationListener(notificationListener);
111
- for (const entry of handler.queue) {
112
- addNotification(entry);
86
+ if (isOpen.value && topNotifications.length === 0) {
87
+ dialogEl.value!.close()
88
+ isOpen.value = false
89
+ }
90
+ }
91
+
92
+ const addNotification = (entry: NotificationEntry) => {
93
+ if (entry.resolution === undefined) {
94
+ if (entry.requiresAction) {
95
+ topNotifications.push(entry)
96
+ open()
97
+ entry.promise.then(() => {
98
+ removeIfIn(topNotifications, entry)
99
+ close()
100
+ })
101
+ } else {
102
+ notifications.splice(0, 0, entry)
103
+ entry.promise.then(() => {
104
+ removeIfIn(notifications, entry)
105
+ })
106
+ }
107
+ }
108
+ }
109
+
110
+ const notificationListener = (entry: NotificationEntry, type: "added" | "resolved" | "deleted"): void => {
111
+ if (type === "added") {
112
+ addNotification(entry)
113
+ }
113
114
  }
115
+
116
+ const handler = props.handler ?? useNotificationHandler()
117
+
118
+ handler.addNotificationListener(notificationListener)
119
+
120
+ for (const entry of handler.queue) { addNotification(entry) }
114
121
  onBeforeUnmount(() => {
115
- handler.removeNotificationListener(notificationListener);
116
- });
122
+ handler.removeNotificationListener(notificationListener)
123
+ })
124
+
117
125
  </script>
126
+ <script lang="ts">
118
127
 
119
- <script>
128
+ type RealProps =
129
+ & LinkableByIdProps
130
+ & {
131
+ /** If not provided, uses the global handler (this requires useNotificationHandler be called and configured). */
132
+ handler?: NotificationHandler
133
+ }
120
134
 
135
+ interface Props
136
+ extends
137
+ /** @vue-ignore */
138
+ Partial<Omit<HTMLAttributes,"class"> & TailwindClassProp>,
139
+ RealProps
140
+ {}
121
141
  </script>
@@ -0,0 +1,6 @@
1
+ import type { Meta, StoryObj } from "@storybook/vue3";
2
+ import LibPagination from "./LibPagination.vue.js";
3
+ declare const meta: Meta<typeof LibPagination>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof LibPagination>;
6
+ export declare const Primary: Story;
@@ -0,0 +1,40 @@
1
+ import { ref } from "vue";
2
+ import LibPagination from "./LibPagination.vue";
3
+ import * as components from "../index.js";
4
+ const meta = {
5
+ component: LibPagination,
6
+ title: "Components/Pagination",
7
+ args: {
8
+ total: 10
9
+ }
10
+ };
11
+ export default meta;
12
+ export const Primary = {
13
+ render: (args) => ({
14
+ components,
15
+ setup() {
16
+ const num = ref(1);
17
+ const changePage = ($event, i) => {
18
+ $event.preventDefault();
19
+ if (i >= 10) num.value = 10;
20
+ if (i <= 1) num.value = 1;
21
+ num.value = i;
22
+ };
23
+ return {
24
+ changePage,
25
+ args,
26
+ num
27
+ };
28
+ },
29
+ template: `
30
+ <lib-pagination v-bind="{...args, current: num, route:'#'}">
31
+ <template #link="linkProps">
32
+ <a v-bind="linkProps" @click="changePage($event, linkProps.i)">{{ linkProps.text ?? linkProps.i }}</a>
33
+ </template>
34
+ </lib-pagination>
35
+ <lib-simple-input :label="'Change Page'" :modelValue="num.toString()" @update:modelValue="num = parseInt($event)" type="number" min="0" :max="args.total">
36
+
37
+ </lib-simple-input>
38
+ `
39
+ })
40
+ };
@@ -3,7 +3,7 @@
3
3
  :class="twMerge(`
4
4
  pagination--wrapper
5
5
  flex flex-wrap items-center justify-center gap-2
6
- `, $attrs.class)"
6
+ `, ($attrs as any).class)"
7
7
  role="navigation"
8
8
  :aria-label="t('pagination.aria')"
9
9
  >
@@ -12,13 +12,13 @@
12
12
  :i="prevLink.i"
13
13
  :href="prevLink.href"
14
14
  :text="t('pagination.previous-page')"
15
- :aria-label="t('pagination.aria.go-to-previous-page', { count: prevLink.i })"
15
+ :aria-label=" t('pagination.aria.go-to-previous-page',{count:prevLink.i})"
16
16
  :class="`pagination--link ${pageClasses}`"
17
17
  >
18
18
  <a
19
19
  :class="`pagination--link ${pageClasses}`"
20
20
  :href="prevLink.href"
21
- :aria-label="t('pagination.aria.go-to-previous-page', { count: prevLink.i })"
21
+ :aria-label=" t('pagination.aria.go-to-previous-page', {count:prevLink.i})"
22
22
  />
23
23
  </slot>
24
24
  <div class="pagination--spacer flex-1"/>
@@ -27,14 +27,14 @@
27
27
  :i="0"
28
28
  :href="firstLink.href"
29
29
  :text="firstLink.i"
30
- :aria-label="t('pagination.aria.go-to-page', { count: firstLink.i })"
30
+ :aria-label="t('pagination.aria.go-to-page', {count:firstLink.i})"
31
31
  :class="`pagination--link pagination--first-link ${pageClasses}`"
32
32
  >
33
33
  {{ firstLink.href }}
34
34
  <a
35
35
  :class="`pagination--link pagination--first-link ${pageClasses}`"
36
36
  :href="firstLink.href"
37
- :aria-label="t('pagination.aria.go-to-page', { count: firstLink.i })"
37
+ :aria-label="t('pagination.aria.go-to-page', {count:firstLink.i})"
38
38
  >
39
39
  {{ firstLink.i }}
40
40
  </a>
@@ -50,12 +50,12 @@
50
50
  :class="`pagination--link ${pageClasses}`"
51
51
  :i="entry.i"
52
52
  :href="entry.href"
53
- :aria-label="t('pagination.aria.go-to-page', { count: entry.i })"
53
+ :aria-label="t('pagination.aria.go-to-page', {count:entry.i})"
54
54
  >
55
55
  <a
56
56
  :class="`pagination--link ${pageClasses}`"
57
57
  :href="entry.href"
58
- :aria-label="t('pagination.aria.go-to-page', { count: entry.i })"
58
+ :aria-label="t('pagination.aria.go-to-page', {count:entry.i})"
59
59
  >
60
60
  {{ entry.i }}
61
61
  </a>
@@ -65,12 +65,12 @@
65
65
  :class="`pagination--link ${currentPageClasses}`"
66
66
  tabindex="0"
67
67
  :i="currentLink.i"
68
- :aria-label="t('pagination.aria.current-page', { count: currentLink.i })"
68
+ :aria-label="t('pagination.aria.current-page', {count:currentLink.i})"
69
69
  :aria_current="true"
70
70
  >
71
71
  <div :class="`pagination--current-page a ${currentPageClasses}`"
72
72
  tabindex="0"
73
- :aria-label="t('pagination.aria.current-page', { count: currentLink.i })"
73
+ :aria-label="t('pagination.aria.current-page', {count:currentLink.i})"
74
74
  aria-current="true"
75
75
  @click="$event.preventDefault()"
76
76
  >
@@ -85,12 +85,12 @@
85
85
  :class="`pagination--link ${pageClasses}`"
86
86
  :i="entry.i"
87
87
  :href="entry.href"
88
- :aria-label="t('pagination.aria.go-to-page', { count: entry.i })"
88
+ :aria-label="t('pagination.aria.go-to-page', {count:entry.i})"
89
89
  >
90
90
  <a
91
91
  :class="`pagination--link ${pageClasses}`"
92
92
  :href="entry.href"
93
- :aria-label="t('pagination.aria.go-to-page', { count: entry.i })"
93
+ :aria-label="t('pagination.aria.go-to-page', {count:entry.i})"
94
94
  >
95
95
  {{ entry.i }}
96
96
  </a>
@@ -105,12 +105,12 @@
105
105
  :i="lastLink.i"
106
106
  :href="lastLink.href"
107
107
  :text="total"
108
- :aria-label="t('pagination.aria.go-to-page', { count: lastLink.i })"
108
+ :aria-label="t('pagination.aria.go-to-page', {count:lastLink.i})"
109
109
  >
110
110
  <a
111
111
  :class="`pagination--link ${pageClasses}`"
112
112
  :href="lastLink.href"
113
- :aria-label="t('pagination.aria.go-to-page', { count: lastLink.i })"
113
+ :aria-label="t('pagination.aria.go-to-page', {count:lastLink.i})"
114
114
  >
115
115
  {{ total }}
116
116
  </a>
@@ -123,25 +123,27 @@
123
123
  :i="nextLink.i"
124
124
  :href="nextLink.href"
125
125
  :text="t('pagination.next-page')"
126
- :aria-label="t('pagination.aria.go-to-next-page', { count: nextLink.i })"
126
+ :aria-label="t('pagination.aria.go-to-next-page', {count:nextLink.i})"
127
127
  >
128
128
  <a
129
129
  :class="`pagination--link ${pageClasses}`"
130
130
  :href="nextLink.href"
131
- :aria-label="t('pagination.aria.go-to-next-page', { count: nextLink.i })"
131
+ :aria-label="t('pagination.aria.go-to-next-page', {count:nextLink.i})"
132
132
  >
133
133
  Next
134
134
  </a>
135
135
  </slot>
136
136
  </nav>
137
137
  </template>
138
+ <script setup lang="ts">
139
+ import { computed, type HTMLAttributes,useAttrs,watch } from "vue"
140
+
141
+ import { useInjectedI18n } from "../../composables/useInjectedI18n.js"
142
+ import { twMerge } from "../../utils/twMerge.js"
143
+ import { type TailwindClassProp } from "../shared/props.js"
144
+
145
+ const t = useInjectedI18n()
138
146
 
139
- <script setup>
140
- import { computed, useAttrs, watch } from "vue";
141
- import { useInjectedI18n } from "../../composables/useInjectedI18n.js";
142
- import { twMerge } from "../../utils/twMerge.js";
143
- import {} from "../shared/props.js";
144
- const t = useInjectedI18n();
145
147
  const commonClasses = `
146
148
  block
147
149
  focus-outline
@@ -149,68 +151,110 @@ const commonClasses = `
149
151
  border-transparent
150
152
  transition-all
151
153
  outlined:rounded-sm
152
- `;
154
+ `
153
155
  const pageClasses = `
154
156
  ${commonClasses}
155
157
  focus-outline
156
158
  hover:text-accent-600
157
159
  hover:border-b-accent-500
158
160
  hover:scale-125
159
- `;
161
+ `
162
+
160
163
  const currentPageClasses = `
161
164
  ${commonClasses}
162
165
  border-b-accent-500
163
166
  scale-125
164
- `;
167
+ `
165
168
  defineOptions({
166
- name: "lib-pagination",
167
- inheritAttrs: false
168
- });
169
- const props = defineProps({
170
- total: { type: Number, required: true },
171
- current: { type: Number, required: true },
172
- route: { type: String, required: true },
173
- customRoute: { type: Function, required: false, default: (route, i) => {
174
- if (i === 0 || i === 1) {
175
- const num = 1;
176
- return { href: route, i: num };
177
- }
178
- return { href: route + i.toString(), i };
179
- } },
180
- extraPages: { type: Number, required: false, default: 3 }
181
- });
182
- const $attrs = useAttrs();
183
- const currentLink = computed(() => props.customRoute(props.route, props.current));
184
- const currentIsInvalid = computed(() => currentLink.value.i < 0 || currentLink.value.i > props.total);
169
+ name: "lib-pagination",
170
+ inheritAttrs: false,
171
+ })
172
+
173
+ const props = withDefaults(defineProps<Props>(), {
174
+ customRoute: (route: string, i: number) => {
175
+ if (i === 0 || i === 1) {
176
+ const num = 1
177
+ return { href: route, i: num }
178
+ }
179
+ return { href: route + i.toString(), i }
180
+ },
181
+ extraPages: 3,
182
+ })
183
+ const $attrs = useAttrs()
184
+
185
+ const currentLink = computed(() => props.customRoute(props.route, props.current))
186
+ const currentIsInvalid = computed(() => currentLink.value.i < 0 || currentLink.value.i > props.total)
187
+
185
188
  watch(() => currentIsInvalid.value, () => {
186
- if (currentIsInvalid.value) {
187
- throw new Error(`Current page is out of range: 0 - ${props.total}`);
188
- }
189
- });
190
- const prevLink = computed(() => props.customRoute(props.route, props.current - 1));
189
+ if (currentIsInvalid.value) {
190
+ throw new Error(`Current page is out of range: 0 - ${props.total}`)
191
+ }
192
+ })
193
+
194
+ const prevLink = computed(() => props.customRoute(props.route, props.current - 1))
195
+
191
196
  const nextLink = computed(() => {
192
- const maybeNextLink = props.customRoute(props.route, props.current + 1);
193
- if (maybeNextLink.i === currentLink.value.i) {
194
- return props.customRoute(props.route, props.current + 2);
195
- }
196
- return maybeNextLink;
197
- });
198
- const firstLink = computed(() => props.customRoute(props.route, 0));
199
- const lastLink = computed(() => props.customRoute(props.route, props.total));
197
+ const maybeNextLink = props.customRoute(props.route, props.current + 1)
198
+ if (maybeNextLink.i === currentLink.value.i) {
199
+ return props.customRoute(props.route, props.current + 2)
200
+ }
201
+ return maybeNextLink
202
+ })
203
+
204
+ const firstLink = computed(() => props.customRoute(props.route, 0))
205
+ const lastLink = computed(() => props.customRoute(props.route, props.total))
206
+
207
+ type HrefInfo = { href: string, i: number }
200
208
  const extraPagesPrev = computed(() => [...Array(props.extraPages)].map((_, _i) => {
201
- const num = currentLink.value.i - (props.extraPages - _i);
202
- if (num <= firstLink.value.i || num >= lastLink.value.i || num >= currentLink.value.i) return void 0;
203
- return props.customRoute(props.route, num);
204
- }).filter((entry) => entry !== void 0));
209
+ const num = currentLink.value.i - (props.extraPages - _i)
210
+ if (num <= firstLink.value.i || num >= lastLink.value.i || num >= currentLink.value.i) return undefined
211
+ return props.customRoute(props.route, num)
212
+ }).filter(entry => entry !== undefined) as HrefInfo[])
213
+
205
214
  const extraPagesNext = computed(() => [...Array(props.extraPages + 1)].map((_, i) => {
206
- const num = currentLink.value.i + i;
207
- if (num <= firstLink.value.i || num >= lastLink.value.i || num <= currentLink.value.i) return void 0;
208
- return props.customRoute(props.route, num);
209
- }).filter((entry) => entry !== void 0).slice(0, props.extraPages));
215
+ const num = currentLink.value.i + i
216
+ if (num <= firstLink.value.i || num >= lastLink.value.i || num <= currentLink.value.i) return undefined
217
+ return props.customRoute(props.route, num)
218
+ }).filter(entry => entry !== undefined).slice(0, props.extraPages) as HrefInfo[])
219
+
210
220
  </script>
221
+ <script lang="ts">
211
222
 
212
- <script>
223
+ /**
224
+ * Pagination component.
225
+ *
226
+ * Can be passed a slot like so to use a custom link element (like NuxtLink):
227
+ * ```vue
228
+ * <template #link="{ href, i, text, ariaLabel, ariaCurrent}">
229
+ * <NuxtLink :to="href" :aria-label="ariaLabel" :aria-current="ariaCurrent ?? false">{{ text ?? i }}</NuxtLink>
230
+ * </template>
231
+ * ```
232
+ */
213
233
  export default {
214
- name: "lib-pagination"
215
- };
234
+ name: "lib-pagination",
235
+ }
236
+ type RealProps = {
237
+ /** The total number of pages. */
238
+ total: number
239
+ /** The number of the current page. It must be valid, between 0 - total or the component will throw an error. */
240
+ current: number
241
+ /** The base route/link path for the page. Should end with a forward slash `/`. */
242
+ route: string
243
+ /**
244
+ * A function to customize the output href and page link number. By default, page 0 is page 1, page 1 is 1, then everything else is normal.
245
+ *
246
+ * This is because usually we have routes like: `/page/1`, `/page/2`, not `/page/0`.
247
+ *
248
+ * You can use this function to customize things further. For example, make `/page/1` just `/`
249
+ */
250
+ customRoute?: (route: string, i: number) => { i: number, href: string }
251
+ /** How many extra pages to show to each side of the current page. */
252
+ extraPages?: number
253
+ }
254
+ interface Props
255
+ extends
256
+ /** @vue-ignore */
257
+ Partial<Omit<HTMLAttributes,"class"> & TailwindClassProp>,
258
+ RealProps
259
+ {}
216
260
  </script>
@@ -0,0 +1,6 @@
1
+ import type { Meta, StoryObj } from "@storybook/vue3";
2
+ import LibPalette from "./LibPalette.vue.js";
3
+ declare const meta: Meta<typeof LibPalette>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof LibPalette>;
6
+ export declare const Primary: Story;
@@ -0,0 +1,20 @@
1
+ import LibPalette from "./LibPalette.vue";
2
+ import { theme } from "../../theme.js";
3
+ import * as components from "../index.js";
4
+ const meta = {
5
+ component: LibPalette,
6
+ title: "Components/Palette",
7
+ args: {
8
+ // theme,
9
+ }
10
+ };
11
+ export default meta;
12
+ export const Primary = {
13
+ render: (args) => ({
14
+ components: { ...components, LibPalette },
15
+ setup: () => ({ args: { ...args, theme } }),
16
+ template: `
17
+ <LibPalette v-bind="{...args}">{{args.value}}</LibPalette>
18
+ `
19
+ })
20
+ };