vueless 0.0.684 → 0.0.686

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "0.0.684",
3
+ "version": "0.0.686",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
6
6
  "keywords": [
@@ -406,6 +406,20 @@ function onToggleExpand(row: Row, expanded: boolean) {
406
406
  }
407
407
  }
408
408
 
409
+ function isRowSelectedWithin(rowIndex: number) {
410
+ const prevRow = sortedRows.value[rowIndex - 1];
411
+ const isPrevRowSelected = prevRow && selectedRows.value.find((rowId) => rowId === prevRow.id);
412
+ const isRowsSelected = selectedRows.value.find(
413
+ (rowId) => rowId === sortedRows.value[rowIndex].id,
414
+ );
415
+
416
+ if (prevRow) {
417
+ return isPrevRowSelected && isRowsSelected;
418
+ }
419
+
420
+ return isRowsSelected;
421
+ }
422
+
409
423
  defineExpose({
410
424
  /**
411
425
  * Allows to clear selected rows.
@@ -438,6 +452,7 @@ const {
438
452
  bodyRowBeforeCellAttrs,
439
453
  footerAttrs,
440
454
  bodyRowDateDividerAttrs,
455
+ bodyRowCheckedDateDividerAttrs,
441
456
  headerCellBaseAttrs,
442
457
  headerCellCheckboxAttrs,
443
458
  headerActionsCheckboxAttrs,
@@ -446,6 +461,7 @@ const {
446
461
  headerCounterAttrs,
447
462
  bodyEmptyStateAttrs,
448
463
  bodyDateDividerAttrs,
464
+ bodySelectedDateDividerAttrs,
449
465
  bodyCellDateDividerAttrs,
450
466
  headerActionsCounterAttrs,
451
467
  stickyHeaderCounterAttrs,
@@ -666,7 +682,10 @@ const {
666
682
  </td>
667
683
  </tr>
668
684
 
669
- <tr v-if="isShownDateDivider(rowIndex) && row.rowDate" v-bind="bodyRowDateDividerAttrs">
685
+ <tr
686
+ v-if="isShownDateDivider(rowIndex) && !isRowSelectedWithin(rowIndex) && row.rowDate"
687
+ v-bind="bodyRowDateDividerAttrs"
688
+ >
670
689
  <td v-bind="bodyCellDateDividerAttrs" :colspan="colsCount">
671
690
  <UDivider
672
691
  size="xs"
@@ -676,6 +695,19 @@ const {
676
695
  </td>
677
696
  </tr>
678
697
 
698
+ <tr
699
+ v-if="isShownDateDivider(rowIndex) && isRowSelectedWithin(rowIndex) && row.rowDate"
700
+ v-bind="bodyRowCheckedDateDividerAttrs"
701
+ >
702
+ <td v-bind="bodyCellDateDividerAttrs" :colspan="colsCount">
703
+ <UDivider
704
+ size="xs"
705
+ :label="getDateDividerLabel(row.rowDate)"
706
+ v-bind="bodySelectedDateDividerAttrs"
707
+ />
708
+ </td>
709
+ </tr>
710
+
679
711
  <UTableRow
680
712
  v-model:selected-rows="selectedRows"
681
713
  :selectable="selectable"
@@ -50,6 +50,7 @@ export default /*tw*/ {
50
50
  bodyRowBeforeCell: "{>bodyCellBase} py-1",
51
51
  bodyRowAfter: "!p-0",
52
52
  bodyRowDateDivider: "",
53
+ bodyRowCheckedDateDivider: "{>bodyRowChecked} {>bodyRowChecked}",
53
54
  bodyCellBase: {
54
55
  base: "p-4 truncate align-top",
55
56
  variants: {
@@ -78,6 +79,10 @@ export default /*tw*/ {
78
79
  base: "{UDivider}",
79
80
  label: "py-0",
80
81
  },
82
+ bodySelectedDateDivider: {
83
+ base: "{>bodyDateDivider}",
84
+ label: "bg-gray-200 transition",
85
+ },
81
86
  bodyEmptyState: "{UEmpty} my-8",
82
87
  footer: {
83
88
  base: "group/footer border-t border-solid border-gray-200",
@@ -124,6 +124,7 @@ const { config, wrapperAttrs, dropdownBadgeAttrs, dropdownListAttrs, dropdownIco
124
124
  v-if="isShownOptions"
125
125
  ref="dropdown-list"
126
126
  :size="size"
127
+ :color="color"
127
128
  :options="options"
128
129
  :label-key="labelKey"
129
130
  v-bind="dropdownListAttrs"
@@ -125,6 +125,7 @@ const { config, dropdownButtonAttrs, dropdownListAttrs, dropdownIconAttrs, wrapp
125
125
  <UDropdownList
126
126
  v-if="isShownOptions"
127
127
  ref="dropdown-list"
128
+ :color="color"
128
129
  :options="options"
129
130
  :label-key="labelKey"
130
131
  v-bind="dropdownListAttrs"
@@ -38,7 +38,7 @@ export default /*tw*/ {
38
38
  size: {
39
39
  "2xs": "sm",
40
40
  xs: "sm",
41
- sm: "sm",
41
+ sm: "md",
42
42
  md: "md",
43
43
  lg: "lg",
44
44
  xl: "lg",
@@ -126,6 +126,7 @@ const { config, getDataTest, wrapperAttrs, dropdownLinkAttrs, dropdownListAttrs,
126
126
  v-if="isShownOptions"
127
127
  ref="dropdown-list"
128
128
  :size="size"
129
+ :color="color"
129
130
  :options="options"
130
131
  :label-key="labelKey"
131
132
  v-bind="dropdownListAttrs"
@@ -8,6 +8,7 @@ import { isMac } from "../utils/platform.ts";
8
8
 
9
9
  import UIcon from "../ui.image-icon/UIcon.vue";
10
10
  import UButton from "../ui.button/UButton.vue";
11
+ import UDivider from "../ui.container-divider/UDivider.vue";
11
12
 
12
13
  import usePointer from "./usePointer.ts";
13
14
  import { useLocale } from "../composables/useLocale.ts";
@@ -136,7 +137,7 @@ function onClickAddOption() {
136
137
  }
137
138
 
138
139
  function isMetaKey(key: string) {
139
- return ["isSubGroup", "groupLabel", "level", "isHidden", "onClick"].includes(key);
140
+ return ["isSubGroup", "groupLabel", "level", "isHidden", "onClick", "divider"].includes(key);
140
141
  }
141
142
 
142
143
  function select(option: Option, keyCode?: string) {
@@ -261,6 +262,7 @@ const {
261
262
  subGroupAttrs,
262
263
  groupAttrs,
263
264
  optionContentAttrs,
265
+ optionDividerAttrs,
264
266
  } = useUI<Config>(defaultConfig);
265
267
  </script>
266
268
 
@@ -285,9 +287,14 @@ const {
285
287
  :role="!(option && option.groupLabel) ? 'option' : undefined"
286
288
  :data-group-label="Boolean(option.groupLabel)"
287
289
  >
290
+ <UDivider v-if="option.divider" padding="none" v-bind="optionDividerAttrs" />
288
291
  <!-- option title -->
289
292
  <span
290
- v-if="!(option && (option.groupLabel || option.isSubGroup)) && !option.isHidden"
293
+ v-if="
294
+ !(option && (option.groupLabel || option.isSubGroup)) &&
295
+ !option.isHidden &&
296
+ !option.divider
297
+ "
291
298
  v-bind="isSelectedOption(option) ? optionActiveAttrs : optionAttrs"
292
299
  :data-test="`${dataTest}-option`"
293
300
  :class="optionHighlight(index, option)"
@@ -11,7 +11,7 @@ export default /*tw*/ {
11
11
  base: `
12
12
  rounded-dynamic-sm px-2 py-2.5 flex items-center align-middle whitespace-nowrap cursor-pointer
13
13
  font-normal !leading-none text-gray-900
14
- hover:bg-brand-50 active:bg-brand-100
14
+ hover:bg-{color}-50 active:bg-{color}-100
15
15
  overflow-hidden text-ellipsis
16
16
  `,
17
17
  variants: {
@@ -21,12 +21,12 @@ export default /*tw*/ {
21
21
  lg: "text-base",
22
22
  },
23
23
  disabled: {
24
- true: "pointer-events-none",
24
+ true: "pointer-events-none text-gray-400",
25
25
  },
26
26
  },
27
27
  },
28
- optionActive: "{>option} font-semibold bg-brand-100 hover:bg-brand-100 text-brand-600",
29
- optionHighlighted: "bg-brand-50",
28
+ optionActive: "{>option} font-semibold bg-{color}-100 hover:bg-{color}-100 text-brand-600",
29
+ optionHighlighted: "bg-{color}-50",
30
30
  optionContent: "overflow-visible text-ellipsis",
31
31
  groupBase: {
32
32
  base: "px-2 pb-2.5 font-medium !leading-none text-gray-400 overflow-hidden text-ellipsis",
@@ -50,11 +50,13 @@ export default /*tw*/ {
50
50
  addOptionLabelHotkey: "text-gray-500",
51
51
  addOptionButton: "{UButton} !leading-none sticky left-[calc(100%-2.15rem)] bottom-2 p-1",
52
52
  addOptionIcon: "{UIcon} bg-transparent",
53
+ optionDivider: "{UDivider}",
53
54
  i18n: {
54
55
  noDataToShow: "No data to show.",
55
56
  add: "Add",
56
57
  },
57
58
  defaults: {
59
+ color: "brand",
58
60
  size: "md",
59
61
  labelKey: "label",
60
62
  valueKey: "id",
@@ -1,4 +1,4 @@
1
- import { Meta, Title, Subtitle, Description, Primary, Controls, Stories, Source } from "@storybook/blocks";
1
+ import { Markdown, Meta, Title, Subtitle, Description, Primary, Controls, Stories, Source } from "@storybook/blocks";
2
2
  import { getSource } from "../../utils/storybook.ts";
3
3
 
4
4
  import * as stories from "./stories.ts";
@@ -12,5 +12,23 @@ import defaultConfig from "../config.ts?raw"
12
12
  <Controls of={stories.Default} />
13
13
  <Stories of={stories} />
14
14
 
15
+ ## Row meta keys
16
+ Keys you may/have to provide to component in an option object.
17
+
18
+ <Markdown>
19
+ {`
20
+ | Key name | Description | Type |
21
+ | ------------------| ---------------------------------- | ---------------|
22
+ | id | A unique identifier for option | String, Number |
23
+ | label | Option label | String |
24
+ | isHidden | Indicates if option is hidden | Boolean |
25
+ | isSubGroup | Indicates if option is subGroup | Boolean |
26
+ | groupLabel | Option group label | String |
27
+ | level | Indicates option nesting level | Number |
28
+ | divider | Adds divider instead of option | Boolean |
29
+ | onClick | Option event handler | Function |
30
+ `}
31
+ </Markdown>
32
+
15
33
  ## Default config
16
34
  <Source code={getSource(defaultConfig)} language="jsx" dark />
@@ -16,7 +16,7 @@ interface DefaultUDropdownListArgs extends Props {
16
16
  }
17
17
 
18
18
  interface EnumUDropdownListArgs extends DefaultUDropdownListArgs {
19
- enum: keyof Pick<Props, "size">;
19
+ enum: keyof Pick<Props, "size" | "color">;
20
20
  }
21
21
 
22
22
  export default {
@@ -25,9 +25,11 @@ export default {
25
25
  component: UDropdownList,
26
26
  args: {
27
27
  options: [
28
- { label: "option 1", id: "1" },
29
- { label: "option 2", id: "2" },
30
- { label: "option 3", id: "3" },
28
+ { label: "New York", id: "1" },
29
+ { label: "Los Angeles", id: "2" },
30
+ { label: "Chicago", id: "3" },
31
+ { label: "Houston", id: "4" },
32
+ { label: "San Francisco", id: "5" },
31
33
  ],
32
34
  },
33
35
  argTypes: {
@@ -37,7 +39,7 @@ export default {
37
39
  docs: {
38
40
  ...getDocsDescription(UDropdownList.__name),
39
41
  story: {
40
- height: "180px",
42
+ height: "250px",
41
43
  },
42
44
  },
43
45
  },
@@ -48,10 +50,16 @@ const DefaultTemplate: StoryFn<DefaultUDropdownListArgs> = (args: DefaultUDropdo
48
50
  setup() {
49
51
  const slots = getSlotNames(UDropdownList.__name);
50
52
 
51
- return { args, slots };
53
+ const showAlert = (message: string) => alert(message);
54
+
55
+ return { args, slots, showAlert };
52
56
  },
53
57
  template: `
54
- <UDropdownList v-bind="args" class="mx-4 w-[24rem]">
58
+ <UDropdownList
59
+ v-bind="args"
60
+ class="mx-4 w-[24rem]"
61
+ @add="showAlert('You triggered the add action!')"
62
+ >
55
63
  ${args.slotTemplate || getSlotsFragment("")}
56
64
  </UDropdownList>
57
65
  `,
@@ -69,27 +77,51 @@ const EnumVariantTemplate: StoryFn<EnumUDropdownListArgs> = (
69
77
  };
70
78
  },
71
79
  template: `
72
- <div class="flex flex-col gap-6">
73
- <URow>
80
+ <URow class="w-fit">
74
81
  <UDropdownList
75
82
  v-for="(option, index) in options"
76
83
  :key="index"
77
84
  v-bind="args"
78
85
  :[args.enum]="option"
86
+ class="static w-36"
79
87
  />
80
88
  </URow>
81
- </div>
82
89
  `,
83
90
  });
84
91
 
85
92
  export const Default = DefaultTemplate.bind({});
86
93
  Default.args = {};
87
94
 
95
+ export const AddOption = DefaultTemplate.bind({});
96
+ AddOption.args = { addOption: true };
97
+ AddOption.parameters = {
98
+ docs: {
99
+ description: {
100
+ story:
101
+ // eslint-disable-next-line vue/max-len
102
+ "The `addOption` prop displays an 'Add option' button, while the `add` event allows handling custom functionality when the button is clicked.",
103
+ },
104
+ },
105
+ };
106
+
88
107
  export const Sizes = EnumVariantTemplate.bind({});
89
108
  Sizes.args = { enum: "size" };
90
109
 
110
+ export const Colors = EnumVariantTemplate.bind({});
111
+ Colors.args = { enum: "color", modelValue: "2" };
112
+
91
113
  export const VisibleOptions = DefaultTemplate.bind({});
92
114
  VisibleOptions.args = { visibleOptions: 3 };
115
+ VisibleOptions.parameters = {
116
+ docs: {
117
+ description: {
118
+ story: "`visibleOptions` prop regulates number of options to show without a scroll.",
119
+ },
120
+ },
121
+ };
122
+
123
+ export const Disabled = DefaultTemplate.bind({});
124
+ Disabled.args = { disabled: true };
93
125
 
94
126
  export const WithoutOptions = DefaultTemplate.bind({});
95
127
  WithoutOptions.args = { options: [] };
@@ -111,16 +143,54 @@ GroupedOptions.args = {
111
143
  { name: "Phoenix" },
112
144
  ],
113
145
  };
146
+ GroupedOptions.parameters = {
147
+ docs: {
148
+ story: {
149
+ height: "500px",
150
+ },
151
+ },
152
+ };
153
+
154
+ export const Divider = DefaultTemplate.bind({});
155
+ Divider.args = {
156
+ options: [
157
+ { label: "North America", id: "1" },
158
+ { label: "South America", id: "2" },
159
+ { divider: true },
160
+ { label: "Europe", id: "3" },
161
+ { divider: true },
162
+ { label: "Asia", id: "4" },
163
+ ],
164
+ };
165
+ Divider.parameters = {
166
+ docs: {
167
+ description: {
168
+ story:
169
+ // eslint-disable-next-line vue/max-len
170
+ "In addition to grouping options, you can insert a divider between specific items by adding an object with a single `divider: true` property.",
171
+ },
172
+ },
173
+ };
114
174
 
115
175
  export const OptionSettings = DefaultTemplate.bind({});
116
176
  OptionSettings.args = {
117
177
  options: [
118
- { label: "option 1", id: "1" },
119
- { label: "option 2", id: "2", isHidden: true },
178
+ { label: "New York", id: "1" },
179
+ { label: "Los Angeles", id: "2", isHidden: true },
120
180
  {
121
- label: "option 3",
181
+ label: "Chicago",
122
182
  id: "3",
123
- onClick: (option: Option) => alert("onClick option 3 " + JSON.stringify(option)),
183
+ onClick: (option: Option) =>
184
+ alert("onClick function for the third option: " + JSON.stringify(option)),
124
185
  },
125
186
  ],
126
187
  };
188
+ OptionSettings.parameters = {
189
+ docs: {
190
+ description: {
191
+ story:
192
+ // eslint-disable-next-line vue/max-len
193
+ "The second option of the array is hidden (`isHidden` object property is set to `true`). <br/> The third option has `onClick` event handler: <br/> `onClick: (option: Option) => alert('onClick function for option 3: ' + JSON.stringify(option))`",
194
+ },
195
+ },
196
+ };
@@ -47,6 +47,32 @@ export interface Props {
47
47
  */
48
48
  size?: "sm" | "md" | "lg";
49
49
 
50
+ /**
51
+ * Option highlight color.
52
+ */
53
+ color?:
54
+ | "grayscale"
55
+ | "red"
56
+ | "orange"
57
+ | "amber"
58
+ | "yellow"
59
+ | "lime"
60
+ | "green"
61
+ | "emerald"
62
+ | "teal"
63
+ | "cyan"
64
+ | "sky"
65
+ | "blue"
66
+ | "indigo"
67
+ | "violet"
68
+ | "purple"
69
+ | "fuchsia"
70
+ | "pink"
71
+ | "rose"
72
+ | "gray"
73
+ | "white"
74
+ | "brand";
75
+
50
76
  /**
51
77
  * Number of options to show without a scroll.
52
78
  */