vueless 0.0.399 → 0.0.401

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.399",
3
+ "version": "0.0.401",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
6
6
  "keywords": [
@@ -201,6 +201,9 @@
201
201
  >
202
202
  <slot :name="`cell-${key}`" :value="slotValues.value" :row="slotValues.row" />
203
203
  </template>
204
+ <template #nested-content>
205
+ <slot v-if="row" name="nested-content" :row="row" />
206
+ </template>
204
207
  </UTableRow>
205
208
 
206
209
  <tr
@@ -18,19 +18,19 @@
18
18
  :class="cx([getCellAttrs(key, row, index).class, columns[index].tdClass])"
19
19
  >
20
20
  <div
21
- v-if="(row.row || nestedLevel) && index === 0"
21
+ v-if="(row.row || nestedLevel || row.nestedData) && index === 0"
22
22
  :style="getNestedShift()"
23
23
  v-bind="bodyCellNestedAttrs"
24
24
  >
25
25
  <UIcon
26
- v-if="row.row"
26
+ v-if="row.row || (row.nestedData && hasSlotContent($slots['nested-content']))"
27
27
  size="xs"
28
28
  internal
29
29
  interactive
30
- :name="row?.row?.isHidden ? config.defaults.expandIcon : config.defaults.collapseIcon"
30
+ :name="getToggleIconName(row)"
31
31
  color="brand"
32
32
  v-bind="toggleIconConfig"
33
- @click="onClickToggleRowChild(row.row.id)"
33
+ @click="onClickToggleRowChild(row.row?.id || row.id)"
34
34
  />
35
35
  </div>
36
36
 
@@ -66,8 +66,20 @@
66
66
  </td>
67
67
  </tr>
68
68
 
69
+ <template
70
+ v-if="row.nestedData && !row.nestedData.isHidden && hasSlotContent($slots['nested-content'])"
71
+ >
72
+ <tr>
73
+ <td :colspan="columns.length + (selectable ? 1 : 0)">
74
+ <div :style="getNestedShift()">
75
+ <slot name="nested-content" :row="row" />
76
+ </div>
77
+ </td>
78
+ </tr>
79
+ </template>
80
+
69
81
  <UTableRow
70
- v-if="row.row && !row.row.isHidden"
82
+ v-if="row.row && !row.row.isHidden && !row.nestedData"
71
83
  v-bind="$attrs"
72
84
  v-model:selected-rows="selectedRows"
73
85
  :attrs="attrs"
@@ -85,6 +97,7 @@
85
97
  <script setup>
86
98
  import { computed, onMounted, ref } from "vue";
87
99
  import { cx } from "../utils/utilUI.js";
100
+ import useUI from "../composables/useUI.js";
88
101
 
89
102
  import { HYPHEN_SYMBOL } from "../constants.js";
90
103
  import { getFilteredRow } from "./utilTable.js";
@@ -94,6 +107,8 @@ import { useMutationObserver } from "../composables/useMutationObserver.js";
94
107
  import UIcon from "../ui.image-icon/UIcon.vue";
95
108
  import UCheckbox from "../ui.form-checkbox/UCheckbox.vue";
96
109
 
110
+ const { hasSlotContent } = useUI();
111
+
97
112
  const props = defineProps({
98
113
  row: {
99
114
  type: Object,
@@ -163,12 +178,18 @@ const toggleIconConfig = computed(() =>
163
178
 
164
179
  const shift = computed(() => (props.row.row ? 1.5 : 2));
165
180
 
181
+ const getToggleIconName = computed(() => (row) => {
182
+ const isHidden = row.row?.isHidden || row.nestedData?.isHidden;
183
+
184
+ return isHidden ? props.config.defaults.expandIcon : props.config.defaults.collapseIcon;
185
+ });
186
+
166
187
  onMounted(() => {
167
188
  cellRef.value.forEach(setElementTitle);
168
189
  });
169
190
 
170
191
  function getCellAttrs(key, row, cellIndex) {
171
- const isNestedRow = (row.row || props.nestedLevel > 0) && cellIndex === 0;
192
+ const isNestedRow = (row.row || row.nestedData || props.nestedLevel > 0) && cellIndex === 0;
172
193
 
173
194
  return isNestedRow ? bodyCellNestedRowAttrs.value : bodyCellBaseAttrs.value;
174
195
  }
@@ -182,7 +203,9 @@ function getNestedCheckboxShift() {
182
203
  }
183
204
 
184
205
  function onClickToggleRowChild(rowId) {
185
- emit("toggleRowVisibility", rowId);
206
+ if (props.row.row || props.row.nestedData) {
207
+ emit("toggleRowVisibility", rowId);
208
+ }
186
209
  }
187
210
 
188
211
  function onClick(row) {
@@ -177,7 +177,7 @@ const DefaultTemplate = (args) => ({
177
177
 
178
178
  if (typeof args.row === "function") {
179
179
  for (let i = 0; i < args.numberOfRows; i++) {
180
- rows.push(args.row());
180
+ rows.push(args.row(i));
181
181
  }
182
182
  } else {
183
183
  rows.push(args.row);
@@ -206,6 +206,92 @@ Default.args = {};
206
206
  export const Nesting = DefaultTemplate.bind({});
207
207
  Nesting.args = { row: getNestedRow, selectable: true };
208
208
 
209
+ export const NestedContent = DefaultTemplate.bind({});
210
+ NestedContent.args = {
211
+ columns: [
212
+ { key: "key_1", label: "Title 1" },
213
+ { key: "key_2", label: "Title 2" },
214
+ { key: "key_3", label: "Title 3" },
215
+ ],
216
+ row: (index) => {
217
+ if (index === 0) {
218
+ return {
219
+ id: getRandomId(),
220
+ isChecked: false,
221
+ key_1: {
222
+ primary: "Row with nested content",
223
+ secondary: "Click to expand",
224
+ },
225
+ key_2: {
226
+ primary: "Primary content",
227
+ secondary: "Secondary content",
228
+ },
229
+ key_3: {
230
+ primary: "More info",
231
+ secondary: "Details below",
232
+ },
233
+ nestedData: {
234
+ isChecked: false,
235
+ isHidden: true,
236
+ rows: [
237
+ {
238
+ id: getRandomId(),
239
+ key_1: "Detail 1A",
240
+ key_2: "Info 1B",
241
+ key_3: "Data 1C",
242
+ },
243
+ {
244
+ id: getRandomId(),
245
+ key_1: "Detail 2A",
246
+ key_2: "Info 2B",
247
+ key_3: "Data 2C",
248
+ },
249
+ {
250
+ id: getRandomId(),
251
+ key_1: "Detail 3A",
252
+ key_2: "Info 3B",
253
+ key_3: "Data 3C",
254
+ },
255
+ ],
256
+ },
257
+ };
258
+ } else {
259
+ return {
260
+ id: getRandomId(),
261
+ isChecked: false,
262
+ key_1: {
263
+ primary: `Regular row ${index}`,
264
+ secondary: "No nested content",
265
+ },
266
+ key_2: {
267
+ primary: "Standard info",
268
+ secondary: "Nothing special",
269
+ },
270
+ key_3: {
271
+ primary: "Basic data",
272
+ secondary: "No details",
273
+ },
274
+ };
275
+ }
276
+ },
277
+ selectable: true,
278
+ slotTemplate: `
279
+ <template #nested-content="{ row }">
280
+ <div class="p-4 bg-gray-100">
281
+ <UTable
282
+ :columns="[
283
+ { key: 'key_1', label: 'Detail' },
284
+ { key: 'key_2', label: 'Info' },
285
+ { key: 'key_3', label: 'Data' },
286
+ ]"
287
+ :rows="row.nestedData.rows"
288
+ compact
289
+ />
290
+ </div>
291
+ </template>
292
+ `,
293
+ };
294
+
209
295
  export const Empty = EmptyTemplate.bind({});
210
296
  Empty.args = {};
211
297
 
@@ -23,11 +23,23 @@ export function syncRowCheck(row, selectedRows) {
23
23
  }
24
24
 
25
25
  export function toggleRowVisibility(row, targetRowId) {
26
- if (row.id === targetRowId) row.isHidden = !row.isHidden;
26
+ if (row.id === targetRowId) {
27
+ if ("isHidden" in row) {
28
+ row.isHidden = !row.isHidden;
29
+ } else if (row.nestedData && "isHidden" in row.nestedData) {
30
+ row.nestedData.isHidden = !row.nestedData.isHidden;
31
+ }
32
+
33
+ return;
34
+ }
27
35
 
28
36
  if (row.row) {
29
37
  toggleRowVisibility(row.row, targetRowId);
30
38
  }
39
+
40
+ if (row.nestedData) {
41
+ toggleRowVisibility(row.nestedData, targetRowId);
42
+ }
31
43
  }
32
44
 
33
45
  export function switchRowCheck(row, isChecked) {
@@ -20,7 +20,7 @@ defineOptions({ inheritAttrs: false });
20
20
 
21
21
  const props = defineProps({
22
22
  /**
23
- * Set loader on.
23
+ * Loader state (shown / hidden).
24
24
  */
25
25
  loading: {
26
26
  type: Boolean,
@@ -4,7 +4,11 @@ import useUI from "../composables/useUI.js";
4
4
  import defaultConfig from "./config.js";
5
5
 
6
6
  export default function useAttrs(props) {
7
- const { config, getKeysAttrs, hasSlotContent } = useUI(defaultConfig, () => props.config);
7
+ const { config, getKeysAttrs, hasSlotContent } = useUI(
8
+ defaultConfig,
9
+ () => props.config,
10
+ "loader",
11
+ );
8
12
 
9
13
  const keysAttrs = getKeysAttrs({}, [], {
10
14
  ellipse: {
@@ -1,12 +1,15 @@
1
1
  <template>
2
2
  <Transition v-bind="config.transition">
3
- <div v-if="showLoader" v-bind="wrapperAttrs">
4
- <ULoader
5
- :loading="showLoader"
6
- size="lg"
7
- :color="color === 'white' ? 'grayscale' : 'white'"
8
- v-bind="loaderAttrs"
9
- />
3
+ <div v-if="showLoader" v-bind="overlayAttrs">
4
+ <!-- @slot Use it to add something instead of the default loader. -->
5
+ <slot>
6
+ <ULoader
7
+ :loading="showLoader"
8
+ size="lg"
9
+ :color="color === 'white' ? 'grayscale' : 'white'"
10
+ v-bind="nestedLoaderAttrs"
11
+ />
12
+ </slot>
10
13
  </div>
11
14
  </Transition>
12
15
  </template>
@@ -26,7 +29,7 @@ defineOptions({ inheritAttrs: false });
26
29
 
27
30
  const props = defineProps({
28
31
  /**
29
- * Set loader on.
32
+ * Loader state (shown / hidden).
30
33
  */
31
34
  loading: {
32
35
  type: Boolean,
@@ -43,7 +46,7 @@ const props = defineProps({
43
46
  },
44
47
  });
45
48
 
46
- const { wrapperAttrs, loaderAttrs, config } = useAttrs(props);
49
+ const { overlayAttrs, nestedLoaderAttrs, config } = useAttrs(props);
47
50
  const { isLoading, loaderRenderingOn, loaderRenderingOff } = useLoaderRendering();
48
51
 
49
52
  onMounted(() => {
@@ -1,5 +1,9 @@
1
1
  export default /*tw*/ {
2
- wrapper: {
2
+ transition: {
3
+ enterFromClass: "scale-110 transform",
4
+ leaveActiveClass: "scale-110 transform",
5
+ },
6
+ overlay: {
3
7
  base: `
4
8
  bg-{color}-600
5
9
  h-screen w-screen
@@ -14,11 +18,7 @@ export default /*tw*/ {
14
18
  },
15
19
  },
16
20
  },
17
- loader: "{ULoader}",
18
- transition: {
19
- enterFromClass: "scale-110 transform",
20
- leaveActiveClass: "scale-110 transform",
21
- },
21
+ nestedLoader: "{ULoader}",
22
22
  defaults: {
23
23
  color: "brand",
24
24
  loading: undefined,
@@ -3,7 +3,11 @@ import useUI from "../composables/useUI.js";
3
3
  import defaultConfig from "./config.js";
4
4
 
5
5
  export default function useAttrs(props) {
6
- const { config, getKeysAttrs, hasSlotContent } = useUI(defaultConfig, () => props.config);
6
+ const { config, getKeysAttrs, hasSlotContent } = useUI(
7
+ defaultConfig,
8
+ () => props.config,
9
+ "overlay",
10
+ );
7
11
 
8
12
  const keysAttrs = getKeysAttrs();
9
13
 
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <Transition :css="false" @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
3
- <div v-if="show" v-bind="progressAttrs" :style="barStyle" />
3
+ <div v-if="show" v-bind="stripeAttrs" :style="barStyle" />
4
4
  </Transition>
5
5
  </template>
6
6
 
@@ -20,7 +20,7 @@ defineOptions({ inheritAttrs: false });
20
20
 
21
21
  const props = defineProps({
22
22
  /**
23
- * The color of the loader stripe.
23
+ * Loader stripe color.
24
24
  * @values brand, grayscale, gray, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose, white
25
25
  */
26
26
  color: {
@@ -44,7 +44,7 @@ const opacity = ref(1);
44
44
  const status = ref(null);
45
45
 
46
46
  const { requestQueue, removeRequestUrl, isLoading, loaderTopOff, loaderTopOn } = useLoaderTop();
47
- const { progressAttrs } = useAttrs(props, { error, isMobileApp });
47
+ const { stripeAttrs } = useAttrs(props, { error, isMobileApp });
48
48
 
49
49
  const isStarted = computed(() => {
50
50
  return typeof status.value === "number";
@@ -1,5 +1,5 @@
1
1
  export default /*tw*/ {
2
- progress: {
2
+ stripe: {
3
3
  base: "top-0 left-0 right-0 fixed h-[3px] transition-all ease-linear bg-{color}-600",
4
4
  variants: {
5
5
  color: {
@@ -11,7 +11,6 @@ export default /*tw*/ {
11
11
  },
12
12
  },
13
13
  },
14
- progressMobile: "mt-safe-top mx-3 rounded max-w-[calc(100%-1.5rem)]",
15
14
  defaults: {
16
15
  color: "brand",
17
16
  },
package/web-types.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "framework": "vue",
3
3
  "name": "vueless",
4
- "version": "0.0.399",
4
+ "version": "0.0.401",
5
5
  "contributions": {
6
6
  "html": {
7
7
  "description-markup": "markdown",
@@ -5825,7 +5825,7 @@
5825
5825
  "attributes": [
5826
5826
  {
5827
5827
  "name": "loading",
5828
- "description": "Set loader on.",
5828
+ "description": "Loader state (shown / hidden).",
5829
5829
  "value": {
5830
5830
  "kind": "expression",
5831
5831
  "type": "boolean"
@@ -5868,7 +5868,7 @@
5868
5868
  "attributes": [
5869
5869
  {
5870
5870
  "name": "loading",
5871
- "description": "Set loader on.",
5871
+ "description": "Loader state (shown / hidden).",
5872
5872
  "value": {
5873
5873
  "kind": "expression",
5874
5874
  "type": "boolean"
@@ -5884,6 +5884,12 @@
5884
5884
  "default": "brand"
5885
5885
  }
5886
5886
  ],
5887
+ "slots": [
5888
+ {
5889
+ "name": "default",
5890
+ "description": "Use it to add something instead of the default loader."
5891
+ }
5892
+ ],
5887
5893
  "source": {
5888
5894
  "module": "./src/ui.loader-rendering/ULoaderRendering.vue",
5889
5895
  "symbol": "default"
@@ -5895,7 +5901,7 @@
5895
5901
  "attributes": [
5896
5902
  {
5897
5903
  "name": "color",
5898
- "description": "The color of the loader stripe.",
5904
+ "description": "Loader stripe color.",
5899
5905
  "value": {
5900
5906
  "kind": "expression",
5901
5907
  "type": "'brand' | 'grayscale' | 'gray' | 'red' | 'orange' | 'amber' | 'yellow' | 'lime' | 'green' | 'emerald' | 'teal' | 'cyan' | 'sky' | 'blue' | 'indigo' | 'violet' | 'purple' | 'fuchsia' | 'pink' | 'rose' | 'white'"
@@ -8253,6 +8259,15 @@
8253
8259
  }
8254
8260
  ]
8255
8261
  },
8262
+ {
8263
+ "name": "nested-content",
8264
+ "scoped": true,
8265
+ "bindings": [
8266
+ {
8267
+ "name": "row"
8268
+ }
8269
+ ]
8270
+ },
8256
8271
  {
8257
8272
  "name": "after-last-row",
8258
8273
  "description": "Use it to add something after last row."
@@ -8370,6 +8385,15 @@
8370
8385
  "name": "row"
8371
8386
  }
8372
8387
  ]
8388
+ },
8389
+ {
8390
+ "name": "nested-content",
8391
+ "scoped": true,
8392
+ "bindings": [
8393
+ {
8394
+ "name": "row"
8395
+ }
8396
+ ]
8373
8397
  }
8374
8398
  ],
8375
8399
  "source": {