vueless 1.4.12-beta.13 → 1.4.12-beta.14

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": "1.4.12-beta.13",
3
+ "version": "1.4.12-beta.14",
4
4
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
5
5
  "author": "Johnny Grid <hello@vueless.com> (https://vueless.com)",
6
6
  "homepage": "https://vueless.com",
@@ -42,6 +42,10 @@ function isCrossed(element: DataListItem) {
42
42
  return Boolean(element.crossed);
43
43
  }
44
44
 
45
+ function hasNestedList(element: DataListItem) {
46
+ return Boolean(element.children?.length || (props.nestedKey && element[props.nestedKey]));
47
+ }
48
+
45
49
  function onDragEnd() {
46
50
  const sortData = prepareSortData(props.list);
47
51
 
@@ -181,14 +185,33 @@ const {
181
185
  </div>
182
186
 
183
187
  <UDataList
184
- v-if="element.children?.length"
188
+ v-if="hasNestedList(element)"
185
189
  hide-empty-state-for-nesting
186
190
  :list="element.children"
187
191
  :group="group"
192
+ :size="size"
193
+ :label-key="labelKey"
194
+ :value-key="valueKey"
195
+ :nested-key="nestedKey"
196
+ :animation-duration="animationDuration"
197
+ :force-fallback="forceFallback"
198
+ :fallback-on-body="fallbackOnBody"
199
+ :fallback-class="fallbackClass"
188
200
  v-bind="nestedAttrs"
201
+ :class="!element.children?.length && 'min-h-4'"
189
202
  :data-test="getDataTest('table')"
190
203
  @drag-sort="onDragEnd"
191
204
  >
205
+ <!-- @vue-ignore -->
206
+ <template #drag="slotProps: { item: DataListItem; iconName: string }">
207
+ <!--
208
+ @slot Use it to add something instead of the drag icon.
209
+ @binding {object} item
210
+ @binding {string} icon-name
211
+ -->
212
+ <slot name="drag" :item="slotProps.item" :icon-name="slotProps.iconName" />
213
+ </template>
214
+
192
215
  <!-- @vue-ignore -->
193
216
  <template #label="slotProps: { item: DataListItem; crossed: boolean }">
194
217
  <!--
@@ -196,12 +219,7 @@ const {
196
219
  @binding {object} item
197
220
  @binding {boolean} crossed
198
221
  -->
199
- <slot name="label" :item="slotProps.item" :crossed="slotProps.crossed">
200
- <div
201
- v-bind="slotProps.crossed ? labelCrossedAttrs : labelAttrs"
202
- v-text="slotProps.item[labelKey]"
203
- />
204
- </slot>
222
+ <slot name="label" :item="slotProps.item" :crossed="slotProps.crossed" />
205
223
  </template>
206
224
 
207
225
  <!-- @vue-ignore -->
@@ -253,6 +253,52 @@ describe("UDataList.vue", () => {
253
253
  expect(nestedComponent.props("list")).toEqual(nestedList[0].children);
254
254
  });
255
255
 
256
+ it("Nesting – renders empty nested drop-zone for childless items when nestedKey is truthy", () => {
257
+ const component = mount(UDataList, {
258
+ props: {
259
+ list: [{ value: 1, label: "Leaf", canNest: true }],
260
+ nestedKey: "canNest",
261
+ },
262
+ });
263
+
264
+ const nestedComponent = component.findComponent("[vl-key='nested']");
265
+
266
+ expect(nestedComponent.exists()).toBe(true);
267
+ });
268
+
269
+ it("Nesting – does not render drop-zone for childless items when nestedKey value is falsy", () => {
270
+ const component = mount(UDataList, {
271
+ props: {
272
+ list: [{ value: 1, label: "Leaf", canNest: false }],
273
+ nestedKey: "canNest",
274
+ },
275
+ });
276
+
277
+ const nestedComponent = component.findComponent("[vl-key='nested']");
278
+
279
+ expect(nestedComponent.exists()).toBe(false);
280
+ });
281
+
282
+ it("Nesting – emits dragged item with parentValue of the leaf after drop into empty drop-zone", async () => {
283
+ const leaf: DataListItem = { value: 1, label: "Leaf", canNest: true, children: [] };
284
+ const list: DataListItem[] = [leaf, { value: 2, label: "Dragged", canNest: true }];
285
+
286
+ const component = mount(UDataList, {
287
+ props: { list, nestedKey: "canNest" },
288
+ });
289
+
290
+ // Simulate vuedraggable moving item 2 into the leaf's (previously empty) nested list.
291
+ list.splice(1, 1);
292
+ leaf.children!.push({ value: 2, label: "Dragged", canNest: true });
293
+
294
+ await component.findComponent(draggable).vm.$emit("end");
295
+
296
+ const sortData = component.emitted("dragSort")?.[0]?.[0] as DataListItem[];
297
+ const dragged = sortData.find((item) => item.value === 2);
298
+
299
+ expect(dragged?.parentValue).toBe(leaf.value);
300
+ });
301
+
256
302
  it("Data Test – applies correct data-test attribute", () => {
257
303
  const dataTest = "test-data-list";
258
304
 
@@ -70,6 +70,12 @@ export interface Props {
70
70
  */
71
71
  hideEmptyStateForNesting?: boolean;
72
72
 
73
+ /**
74
+ * Item key whose truthy value renders an empty nested drop-zone,
75
+ * so a deeper level can be created by drag even without children.
76
+ */
77
+ nestedKey?: string;
78
+
73
79
  /**
74
80
  * Component config object.
75
81
  */
@@ -227,7 +227,7 @@ async function findAndCopyIcons(files, library, vuelessConfig, debug) {
227
227
  const iconPropsPattern = `\\b\\w*(name|icon)\\w*\\s*=\\s*(['"])(.*?)\\2`;
228
228
  const uComponentIconNamePattern =
229
229
  // eslint-disable-next-line vue/max-len
230
- /<UIcon\b[^>]*?\b(name)\s*[:=]\s*(['"])(.*?)\2[^>]*?>|<(?!UIcon\b)(U\w+)\b[^>]*?\b(\w*icon\w*)\s*[:=]\s*(['"])(.*?)\6[^>]*?>/;
230
+ /<UIcon\b[^>]*?\b(name)\s*[:=]\s*(['"])(.*?)\2[^>]*?>|<(?!UIcon\b)([A-Z]\w+)\b[^>]*?\b(\w*icon\w*)\s*[:=]\s*(['"])(.*?)\6[^>]*?>/;
231
231
 
232
232
  const uComponentIconNameArray = fileContents.match(new RegExp(uComponentIconNamePattern, "g"));
233
233