vueless 0.0.686 → 0.0.688

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.
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 -960 960 960"><path d="M395.93-270.2v-419.6L605.74-480 395.93-270.2Z"/></svg>
package/constants.js CHANGED
@@ -147,6 +147,7 @@ export const COMPONENTS = {
147
147
  UTabs: "ui.navigation-tabs",
148
148
  UProgress: "ui.navigation-progress",
149
149
  UPagination: "ui.navigation-pagination",
150
+ UBreadcrumbs: "ui.navigation-breadcrumbs",
150
151
 
151
152
  /* Loaders and Skeletons */
152
153
  ULoader: "ui.loader",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "0.0.686",
3
+ "version": "0.0.688",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
6
6
  "keywords": [
package/types.ts CHANGED
@@ -37,6 +37,7 @@ import UPaginationConfig from "./ui.navigation-pagination/config.ts";
37
37
  import UProgressConfig from "./ui.navigation-progress/config.ts";
38
38
  import UTabConfig from "./ui.navigation-tab/config.ts";
39
39
  import UTabsConfig from "./ui.navigation-tabs/config.ts";
40
+ import UBreadcrumbsConfig from "./ui.navigation-breadcrumbs/config.ts";
40
41
  import UAvatarConfig from "./ui.image-avatar/config.ts";
41
42
  import UIconConfig from "./ui.image-icon/config.ts";
42
43
  import UCheckboxConfig from "./ui.form-checkbox/config.ts";
@@ -226,6 +227,7 @@ export interface Components {
226
227
  UProgress: Partial<typeof UProgressConfig>;
227
228
  UTab: Partial<typeof UTabConfig>;
228
229
  UTabs: Partial<typeof UTabsConfig>;
230
+ UBreadcrumbs: Partial<typeof UBreadcrumbsConfig>;
229
231
  UAvatar: Partial<typeof UAvatarConfig>;
230
232
  UIcon: Partial<typeof UIconConfig>;
231
233
  UCheckbox: Partial<typeof UCheckboxConfig>;
@@ -9,7 +9,7 @@ import { getDefaults } from "../utils/ui.ts";
9
9
  import defaultConfig from "./config.ts";
10
10
  import { COMPONENT_NAME } from "./constants.ts";
11
11
 
12
- import type { Props, Config } from "./types.ts";
12
+ import type { Props, Config, ULinkSlotProps } from "./types.ts";
13
13
 
14
14
  defineOptions({ inheritAttrs: false });
15
15
 
@@ -101,6 +101,7 @@ const { getDataTest, linkAttrs } = useUI<Config>(defaultConfig, mutatedProps);
101
101
  <template>
102
102
  <router-link
103
103
  v-if="isPresentRoute"
104
+ v-slot="slotProps: ULinkSlotProps"
104
105
  :to="safeTo"
105
106
  :custom="custom"
106
107
  :replace="replace"
@@ -118,8 +119,14 @@ const { getDataTest, linkAttrs } = useUI<Config>(defaultConfig, mutatedProps);
118
119
  @keydown="onKeydown"
119
120
  @mouseover="onMouseover"
120
121
  >
121
- <!-- @slot Use it replace the label. -->
122
- <slot>{{ label }}</slot>
122
+ <!--
123
+ @slot Use it replace the label.
124
+ @binding {boolean} is-active
125
+ @binding {boolean} is-exact-active
126
+ -->
127
+ <slot :is-active="slotProps.isActive" :is-exact-active="slotProps.isExactActive">
128
+ {{ label }}
129
+ </slot>
123
130
  </router-link>
124
131
 
125
132
  <a
@@ -5,6 +5,11 @@ import type { RouteLocationRaw } from "vue-router";
5
5
 
6
6
  export type Config = typeof defaultConfig;
7
7
 
8
+ export interface ULinkSlotProps {
9
+ isActive: boolean;
10
+ isExactActive: boolean;
11
+ }
12
+
8
13
  export interface Props {
9
14
  /**
10
15
  * Button label.
@@ -0,0 +1,122 @@
1
+ <script setup lang="ts">
2
+ import { computed } from "vue";
3
+
4
+ import useUI from "../composables/useUI.ts";
5
+ import { getDefaults } from "../utils/ui.ts";
6
+
7
+ import defaultConfig from "./config.ts";
8
+ import { COMPONENT_NAME } from "./constants.ts";
9
+
10
+ import ULink from "../ui.button-link/ULink.vue";
11
+ import UIcon from "../ui.image-icon/UIcon.vue";
12
+
13
+ import type { Props, Config, UBreadcrumb } from "./types.ts";
14
+ import type { ULinkSlotProps } from "../ui.button-link/types.ts";
15
+
16
+ defineOptions({ inheritAttrs: false });
17
+
18
+ const props = withDefaults(defineProps<Props>(), {
19
+ ...getDefaults<Props, Config>(defaultConfig, COMPONENT_NAME),
20
+ links: () => [],
21
+ });
22
+
23
+ const emit = defineEmits([
24
+ /**
25
+ * Triggers on a link click.
26
+ * @property {object} link
27
+ */
28
+ "clickLink",
29
+ ]);
30
+
31
+ const getIconColor = computed(() => {
32
+ return (link: UBreadcrumb) => (link.disabled || (!link.to && !link.href) ? "gray" : props.color);
33
+ });
34
+
35
+ function onClickLink(link: UBreadcrumb) {
36
+ emit("clickLink", link);
37
+ }
38
+
39
+ /**
40
+ * Get element / nested component attributes for each config token ✨
41
+ * Applies: `class`, `config`, redefined default `props` and dev `vl-...` attributes.
42
+ */
43
+ const { config, breadcrumbsAttrs, breadcrumbLinkAttrs, breadcrumbIconAttrs, dividerIconAttrs } =
44
+ useUI<Config>(defaultConfig);
45
+ </script>
46
+
47
+ <template>
48
+ <div v-bind="breadcrumbsAttrs">
49
+ <template v-for="(link, index) in links" :key="index">
50
+ <!--
51
+ @slot Use it to add something instead of a link icon.
52
+ @binding {string} icon-name
53
+ @binding {number} index
54
+ -->
55
+ <slot name="icon" :icon-name="link.icon" :index="index">
56
+ <UIcon
57
+ v-if="link.icon"
58
+ :name="link.icon"
59
+ :color="getIconColor(link)"
60
+ v-bind="breadcrumbIconAttrs"
61
+ />
62
+ </slot>
63
+
64
+ <ULink
65
+ :label="link.label"
66
+ :href="link.href"
67
+ :to="link.to"
68
+ :size="size"
69
+ :color="color"
70
+ :target="link.target || target"
71
+ :custom="link.custom"
72
+ :replace="link.replace"
73
+ :active-class="link.activeClass"
74
+ :exact-active-class="link.exactActiveClass"
75
+ :aria-current-value="link.ariaCurrentValue"
76
+ :underlined="underlined"
77
+ :dashed="dashed"
78
+ :disabled="link.disabled || (!link.to && !link.href)"
79
+ :ring="false"
80
+ v-bind="breadcrumbLinkAttrs"
81
+ :data-test="dataTest"
82
+ @click="onClickLink(link)"
83
+ >
84
+ <template #default="slotProps">
85
+ <!--
86
+ @slot Use it to add something instead of a link label.
87
+ @binding {string} label
88
+ @binding {number} index
89
+ @binding {boolean} active
90
+ @binding {boolean} exact-active
91
+ -->
92
+ <slot
93
+ name="label"
94
+ :label="link.label"
95
+ :index="index"
96
+ :active="(slotProps as ULinkSlotProps).isActive"
97
+ :exact-active="(slotProps as ULinkSlotProps).isExactActive"
98
+ />
99
+ </template>
100
+ </ULink>
101
+
102
+ <!--
103
+ @slot Use it to add something instead of the divider.
104
+ @binding {string} icon-name
105
+ @binding {number} index
106
+ -->
107
+ <slot
108
+ v-if="links.length !== index + 1"
109
+ name="divider"
110
+ :icon-name="config.defaults.dividerIcon"
111
+ :index="index"
112
+ >
113
+ <UIcon
114
+ v-if="links.length !== index + 1"
115
+ :name="config.defaults.dividerIcon"
116
+ :color="getIconColor(link)"
117
+ v-bind="dividerIconAttrs"
118
+ />
119
+ </slot>
120
+ </template>
121
+ </div>
122
+ </template>
@@ -0,0 +1,32 @@
1
+ export default /*tw*/ {
2
+ breadcrumbs: "flex items-center gap-1 py-2",
3
+ breadcrumbLink: "{ULink}",
4
+ breadcrumbIcon: {
5
+ base: "{UIcon}",
6
+ defaults: {
7
+ size: {
8
+ sm: "2xs",
9
+ md: "xs",
10
+ lg: "sm",
11
+ },
12
+ },
13
+ },
14
+ dividerIcon: {
15
+ base: "{UIcon}",
16
+ defaults: {
17
+ size: {
18
+ sm: "xs",
19
+ md: "sm",
20
+ lg: "md",
21
+ },
22
+ },
23
+ },
24
+ defaults: {
25
+ color: "grayscale",
26
+ size: "md",
27
+ underlined: undefined,
28
+ dashed: false,
29
+ target: "_self",
30
+ dividerIcon: "arrow_right",
31
+ },
32
+ };
@@ -0,0 +1,5 @@
1
+ /*
2
+ This const is needed to prevent the issue in script setup:
3
+ `defineProps` is referencing locally declared variables. (vue/valid-define-props)
4
+ */
5
+ export const COMPONENT_NAME = "UBreadcrumbs";
@@ -0,0 +1,37 @@
1
+ import { Markdown, Meta, Title, Subtitle, Description, Primary, Controls, Stories, Source } from "@storybook/blocks";
2
+ import { getSource } from "../../utils/storybook.ts";
3
+
4
+ import * as stories from "./stories.ts";
5
+ import defaultConfig from "../config.ts?raw"
6
+
7
+ <Meta of={stories} />
8
+ <Title of={stories} />
9
+ <Subtitle of={stories} />
10
+ <Description of={stories} />
11
+ <Primary of={stories} />
12
+ <Controls of={stories.Default} />
13
+ <Stories of={stories} />
14
+
15
+ ## Breadcrumb Link Object Properties
16
+ Keys you may/have to provide to the component in a `link` object.
17
+
18
+ <Markdown>
19
+ {`
20
+ | Key name | Description | Type |
21
+ | ---------------------- | ----------------------------------------------------- | ----------------------- |
22
+ | label | Link label | String |
23
+ | route | Route object | Object |
24
+ | href | Link URL | String |
25
+ | disabled | Used to disable link | Boolean |
26
+ | icon | Icon name | String |
27
+ | target | Specifies where to open the linked page. | String |
28
+ | custom | Whether RouterLink should not wrap content in a tag | Boolean |
29
+ | replace | Whether to replace current history entry | Boolean |
30
+ | activeClass | Classes to apply when route is active | String |
31
+ | exactActiveClass | Classes to apply when route is exactly active | String |
32
+ | ariaCurrentValue | Value for aria-current when link is exact active | String |
33
+ `}
34
+ </Markdown>
35
+
36
+ ## Default config
37
+ <Source code={getSource(defaultConfig)} language="jsx" dark />
@@ -0,0 +1,156 @@
1
+ import { getArgTypes, getSlotNames, getSlotsFragment } from "../../utils/storybook.ts";
2
+
3
+ import UBreadcrumbs from "../../ui.navigation-breadcrumbs/UBreadcrumbs.vue";
4
+ import UCol from "../../ui.container-col/UCol.vue";
5
+ import UBadge from "../../ui.text-badge/UBadge.vue";
6
+ import UButton from "../../ui.button/UButton.vue";
7
+
8
+ import type { Meta, StoryFn } from "@storybook/vue3";
9
+ import type { Props } from "../types.ts";
10
+
11
+ interface UBreadcrumbsArgs extends Props {
12
+ slotTemplate?: string;
13
+ enum: "size";
14
+ }
15
+
16
+ interface UBreadcrumbsArgs extends Props {
17
+ slotTemplate?: string;
18
+ }
19
+
20
+ export default {
21
+ id: "8030",
22
+ title: "Navigation / Breadcrumbs",
23
+ component: UBreadcrumbs,
24
+ args: {
25
+ links: [
26
+ { label: "Vueless Docs", href: "https://docs.vueless.com/" },
27
+ { label: "Global Customization", href: "https://docs.vueless.com/global-customization/" },
28
+ { label: "Rounding", href: "https://docs.vueless.com/global-customization/rounding" },
29
+ ],
30
+ target: "_blank",
31
+ },
32
+ argTypes: {
33
+ ...getArgTypes(UBreadcrumbs.__name),
34
+ },
35
+ } as Meta;
36
+
37
+ const DefaultTemplate: StoryFn<UBreadcrumbsArgs> = (args: UBreadcrumbsArgs) => ({
38
+ components: { UBreadcrumbs },
39
+ setup() {
40
+ const slots = getSlotNames(UBreadcrumbs.__name);
41
+
42
+ return { args, slots };
43
+ },
44
+ template: `
45
+ <UBreadcrumbs v-bind="args">
46
+ ${args.slotTemplate || getSlotsFragment("")}
47
+ </UBreadcrumbs>
48
+ `,
49
+ });
50
+
51
+ const EnumVariantTemplate: StoryFn<UBreadcrumbsArgs> = (args: UBreadcrumbsArgs, { argTypes }) => ({
52
+ components: { UBreadcrumbs, UCol },
53
+ setup() {
54
+ return {
55
+ args,
56
+ options: argTypes?.[args.enum]?.options,
57
+ };
58
+ },
59
+ template: `
60
+ <UCol>
61
+ <UBreadcrumbs
62
+ v-for="(option, index) in options"
63
+ :key="index"
64
+ v-bind="args"
65
+ :[args.enum]="option"
66
+ />
67
+ </UCol>
68
+ `,
69
+ });
70
+
71
+ export const Default = DefaultTemplate.bind({});
72
+ Default.args = {};
73
+
74
+ export const Sizes = EnumVariantTemplate.bind({});
75
+ Sizes.args = { enum: "size" };
76
+
77
+ export const Styles = DefaultTemplate.bind({});
78
+ Styles.args = { color: "green", dashed: true };
79
+ Styles.parameters = {
80
+ docs: {
81
+ description: {
82
+ story:
83
+ "For a full list of ULink's supported colors, underlined/dashed styles, etc., see the [ULink Documentation](https://ui.vueless.com/?path=/docs/1060--docs).",
84
+ },
85
+ },
86
+ };
87
+
88
+ export const LinkStates = DefaultTemplate.bind({});
89
+ LinkStates.args = {
90
+ links: [
91
+ { label: "Default link", href: "https://vueless.com/" },
92
+ { label: "Empty link (no `route` or `href` properties)" },
93
+ {
94
+ label: "Manually disabled link",
95
+ href: "https://docs.vueless.com/",
96
+ disabled: true,
97
+ },
98
+ ],
99
+ };
100
+ LinkStates.parameters = {
101
+ docs: {
102
+ description: {
103
+ story:
104
+ // eslint-disable-next-line vue/max-len
105
+ "A breadcrumb is automatically disabled, if: <br /> - it does not have both `route` and `href` properties; <br /> - it has `disabled` property set to `true.",
106
+ },
107
+ },
108
+ };
109
+
110
+ export const LinkIcon = DefaultTemplate.bind({});
111
+ LinkIcon.args = {
112
+ links: [
113
+ { label: "Vueless", href: "https://vueless.com/", icon: "palette" },
114
+ { label: "Settings", icon: "settings" },
115
+ { label: "Breadcrumbs", href: "https://ui.vueless.com/?path=/docs/8030--docs" },
116
+ ],
117
+ };
118
+ LinkIcon.parameters = {
119
+ docs: {
120
+ description: {
121
+ story:
122
+ "You can pass an icon for a specific breadcrumb in the `links` array via the `icon` property.",
123
+ },
124
+ },
125
+ };
126
+
127
+ export const Slots: StoryFn<UBreadcrumbsArgs> = (args) => ({
128
+ components: { UBreadcrumbs, UBadge, UButton },
129
+ setup() {
130
+ return { args };
131
+ },
132
+ template: `
133
+ <UBreadcrumbs v-bind="args">
134
+ <template #icon="{ index }">
135
+ <UBadge
136
+ v-if="index === 1"
137
+ label="Info"
138
+ color="green"
139
+ size="sm"
140
+ />
141
+ </template>
142
+ </UBreadcrumbs>
143
+
144
+ <UBreadcrumbs v-bind="args">
145
+ <template #label="{ label, index }">
146
+ <UButton v-if="index === 0" :label="label" size="2xs" />
147
+ </template>
148
+ </UBreadcrumbs>
149
+
150
+ <UBreadcrumbs v-bind="args">
151
+ <template #divider="{ index }">
152
+ <span>/</span>
153
+ </template>
154
+ </UBreadcrumbs>
155
+ `,
156
+ });
@@ -0,0 +1,72 @@
1
+ import defaultConfig from "./config.ts";
2
+ import type { ComponentConfig } from "../types.ts";
3
+ import type { Props as ULinkProps } from "../ui.button-link/types.ts";
4
+
5
+ export type Config = typeof defaultConfig;
6
+
7
+ export interface UBreadcrumb extends ULinkProps {
8
+ icon?: string;
9
+ }
10
+
11
+ export interface Props {
12
+ /**
13
+ * Array of links.
14
+ */
15
+ links?: UBreadcrumb[];
16
+
17
+ /**
18
+ * Breadcrumbs' size.
19
+ */
20
+ size?: "sm" | "md" | "lg";
21
+
22
+ /**
23
+ * Breadcrumbs' color.
24
+ */
25
+ color?:
26
+ | "grayscale"
27
+ | "red"
28
+ | "orange"
29
+ | "amber"
30
+ | "yellow"
31
+ | "lime"
32
+ | "green"
33
+ | "emerald"
34
+ | "teal"
35
+ | "cyan"
36
+ | "sky"
37
+ | "blue"
38
+ | "indigo"
39
+ | "violet"
40
+ | "purple"
41
+ | "fuchsia"
42
+ | "pink"
43
+ | "rose"
44
+ | "gray"
45
+ | "white"
46
+ | "brand";
47
+
48
+ /**
49
+ * Specifies where to open the linked page.
50
+ */
51
+ target?: "_blank" | "_self" | "_parent" | "_top" | string;
52
+
53
+ /**
54
+ * Show underline.
55
+ */
56
+ underlined?: boolean;
57
+
58
+ /**
59
+ * Set breadcrumbs' underline style as dashed.
60
+ */
61
+ dashed?: boolean;
62
+
63
+ /**
64
+ * Component config object.
65
+ */
66
+ config?: ComponentConfig<Config>;
67
+
68
+ /**
69
+ * Data-test attribute for automated testing.
70
+ */
71
+ dataTest?: string;
72
+ }
@@ -189,7 +189,7 @@ async function findAndCopyIcons(files) {
189
189
  const iconName = groupMatch ? groupMatch[3] : null;
190
190
 
191
191
  try {
192
- if (!iconName) return;
192
+ if (!iconName) continue;
193
193
 
194
194
  if (iconName?.includes("?") && iconName?.includes(":")) {
195
195
  const [trueName, falseName] = getTernaryValues(iconName);