@ulu/frontend-vue 0.5.3 → 0.5.5

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 (41) hide show
  1. package/dist/components/elements/UluCounterList.vue.d.ts +32 -0
  2. package/dist/components/elements/UluCounterList.vue.d.ts.map +1 -0
  3. package/dist/components/elements/UluCounterList.vue.js +77 -0
  4. package/dist/components/elements/UluDataTable.vue.d.ts +43 -0
  5. package/dist/components/elements/UluDataTable.vue.d.ts.map +1 -0
  6. package/dist/components/elements/UluDataTable.vue.js +114 -0
  7. package/dist/components/elements/UluDefinitionList.vue.d.ts +2 -2
  8. package/dist/components/elements/UluList.vue.d.ts +4 -0
  9. package/dist/components/elements/UluList.vue.d.ts.map +1 -1
  10. package/dist/components/elements/UluList.vue.js +40 -23
  11. package/dist/components/elements/UluListItem.vue.d.ts +4 -2
  12. package/dist/components/elements/UluListItem.vue.d.ts.map +1 -1
  13. package/dist/components/elements/UluListItem.vue.js +17 -10
  14. package/dist/components/elements/UluTable.vue.d.ts +48 -0
  15. package/dist/components/elements/UluTable.vue.d.ts.map +1 -0
  16. package/dist/components/elements/UluTable.vue.js +211 -0
  17. package/dist/components/index.d.ts +3 -0
  18. package/dist/components/systems/table-sticky/UluTableSticky.vue.d.ts +104 -104
  19. package/dist/components/systems/table-sticky/UluTableSticky.vue.d.ts.map +1 -1
  20. package/dist/components/systems/table-sticky/UluTableSticky.vue.js +218 -256
  21. package/dist/components/systems/table-sticky/UluTableStickyRows.vue.d.ts +4 -4
  22. package/dist/components/systems/table-sticky/UluTableStickyTable.vue.d.ts +12 -12
  23. package/dist/components/utils/UluAction.vue.js +1 -1
  24. package/dist/components/utils/UluPlaceholderImage.vue.d.ts +2 -2
  25. package/dist/composables/index.d.ts +1 -0
  26. package/dist/composables/useTableData.d.ts +30 -0
  27. package/dist/composables/useTableData.d.ts.map +1 -0
  28. package/dist/composables/useTableData.js +68 -0
  29. package/dist/index.js +190 -182
  30. package/lib/components/elements/UluCounterList.vue +77 -0
  31. package/lib/components/elements/UluDataTable.vue +115 -0
  32. package/lib/components/elements/UluDefinitionList.vue +1 -1
  33. package/lib/components/elements/UluList.vue +23 -8
  34. package/lib/components/elements/UluListItem.vue +11 -6
  35. package/lib/components/elements/UluTable.vue +217 -0
  36. package/lib/components/index.js +3 -0
  37. package/lib/components/systems/table-sticky/UluTableSticky.vue +26 -171
  38. package/lib/components/utils/UluAction.vue +1 -1
  39. package/lib/composables/index.js +1 -0
  40. package/lib/composables/useTableData.js +189 -0
  41. package/package.json +3 -3
@@ -0,0 +1,77 @@
1
+ <template>
2
+ <UluList
3
+ class="counter-list"
4
+ :class="resolvedModifiers"
5
+ :items="items"
6
+ :element="element"
7
+ :itemElement="itemElement"
8
+ :classes="resolvedClasses"
9
+ >
10
+ <template v-if="$slots.default" #default="slotProps">
11
+ <slot v-bind="slotProps" />
12
+ </template>
13
+ </UluList>
14
+ </template>
15
+
16
+ <script setup>
17
+ import { computed } from "vue";
18
+ import { useModifiers } from "../../composables/useModifiers.js";
19
+ import UluList from "./UluList.vue";
20
+
21
+ const props = defineProps({
22
+ /**
23
+ * Array of list items, output as is or use slot to template the item
24
+ * - Note item can add classes by defining { classes: { item } }
25
+ */
26
+ items: Array,
27
+ /**
28
+ * HTML element for the list
29
+ */
30
+ element: {
31
+ type: String,
32
+ default: "ol"
33
+ },
34
+ /**
35
+ * HTML element for the list items (when using items array)
36
+ */
37
+ itemElement: {
38
+ type: String,
39
+ default: "li"
40
+ },
41
+ /**
42
+ * Classes object (keys are { list, item } to be applied to list and item elements)
43
+ */
44
+ classes: {
45
+ type: Object,
46
+ default: () => ({})
47
+ },
48
+ /**
49
+ * Use alphabetical counter
50
+ */
51
+ alphabetical: Boolean,
52
+ /**
53
+ * Remove counter reset
54
+ */
55
+ noReset: Boolean,
56
+ /**
57
+ * Modifiers (to add any modifier classes based on base class [ie. 'alphabetical'])
58
+ */
59
+ modifiers: [String, Array]
60
+ });
61
+
62
+ const { resolvedModifiers } = useModifiers({
63
+ props,
64
+ baseClass: "counter-list",
65
+ internal: computed(() => ({
66
+ "alphabetical": props.alphabetical,
67
+ "no-reset": props.noReset
68
+ }))
69
+ });
70
+
71
+ const resolvedClasses = computed(() => {
72
+ return {
73
+ list: props.classes.list,
74
+ item: ["counter-list__item", props.classes.item]
75
+ };
76
+ });
77
+ </script>
@@ -0,0 +1,115 @@
1
+ <template>
2
+ <UluTable
3
+ class="data-table"
4
+ v-bind="$attrs"
5
+ :columns="columns"
6
+ :rows="rows"
7
+ :footerRows="footerRows"
8
+ :caption="caption"
9
+ :idPrefix="idPrefix"
10
+ :getRowValue="getRowValue"
11
+ :getColumnTitle="getColumnTitle"
12
+ :classes="{
13
+ ...classes,
14
+ table: [resolvedModifiers, classes?.table]
15
+ }"
16
+ >
17
+ <template v-for="(_, name) in $slots" v-slot:[name]="slotData">
18
+ <slot :name="name" v-bind="slotData" />
19
+ </template>
20
+ </UluTable>
21
+ </template>
22
+
23
+ <script setup>
24
+ import { computed } from "vue";
25
+ import { useModifiers } from "../../composables/useModifiers.js";
26
+ import UluTable from "./UluTable.vue";
27
+ import { isArrayOfObjects } from "../../utils/props.js";
28
+
29
+ const props = defineProps({
30
+ /**
31
+ * Array of column configurations to convert to list output
32
+ *
33
+ * @property {Object} column A column config
34
+ * @property {String|Boolean} column.title The title to output for the column if set to a falsey value nothing will print
35
+ * @property {Array} column.columns Array of child columns
36
+ * @property {String} column.key The key that should be usec to grab column's value from rows
37
+ * @property {Function} column.value A function that returns the column's value used instead of key passed (row, column)
38
+ * @property {String} column.slot Register custom slot name to use as a template for this column. Passing a slot with this name will link them. The slot are passed the ({row, column}). Note this will disable output of the column's value
39
+ * @property {String} column.slotHeader Register custom slot name to use in the header
40
+ * @property {String} column.classHeader Custom class(s) to be set to column <th>
41
+ * @property {String} column.class Custom class(s) to be set to column's value <td>
42
+ * @property {String} column.html Use v-html output for value
43
+ * @property {String} column.rowHeader When this column is printed in the <tbody> it should be a header for the row. Note supports multiple row headers from left to right only. No rowspan support for rowHeaders.
44
+ */
45
+ columns: {
46
+ type: Array,
47
+ validator: isArrayOfObjects
48
+ },
49
+ /**
50
+ * Array of tables rows (tbody)
51
+ * - Each row is an object who's value will be matched to columns
52
+ */
53
+ rows: {
54
+ type: Array,
55
+ validator: isArrayOfObjects
56
+ },
57
+ /**
58
+ * Array of rows for footer (tfoot)
59
+ */
60
+ footerRows: {
61
+ type: Array,
62
+ validator: isArrayOfObjects
63
+ },
64
+ /**
65
+ * Hidden caption for accessibility (or visible depending on styles). Can also be passed via slot.
66
+ */
67
+ caption: String,
68
+ /**
69
+ * Prefix used for id generation
70
+ */
71
+ idPrefix: String,
72
+ /**
73
+ * Optional user overridden value getter (for rows)
74
+ * @param {Object} row The current row
75
+ * @param {Object} column The current column in the row
76
+ */
77
+ getRowValue: Function,
78
+ /**
79
+ * Optional user overridden title getter (for headers)
80
+ * @param {Object} column The current column
81
+ */
82
+ getColumnTitle: Function,
83
+
84
+ /**
85
+ * Applies striped row styling
86
+ */
87
+ striped: Boolean,
88
+ /**
89
+ * Enhances the first column's visual prominence
90
+ */
91
+ largeFirst: Boolean,
92
+ /**
93
+ * Additional style modifiers
94
+ */
95
+ modifiers: [String, Array],
96
+
97
+ /**
98
+ * Allows user to pass classes object to add custom classes to parts of the component
99
+ */
100
+ classes: {
101
+ type: Object,
102
+ default: () => ({})
103
+ }
104
+ });
105
+
106
+ const { resolvedModifiers } = useModifiers({
107
+ props,
108
+ baseClass: "data-table",
109
+ internal: computed(() => ({
110
+ 'striped': props.striped,
111
+ 'large-first': props.largeFirst
112
+ }))
113
+ });
114
+
115
+ </script>
@@ -33,7 +33,7 @@
33
33
  </dd>
34
34
  </div>
35
35
  </template>
36
- <slot v-else></slot>
36
+ <slot v-else />
37
37
  </dl>
38
38
  </template>
39
39
 
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <component
3
3
  v-if="items !== undefined ? items.length : $slots.default"
4
- :is="listElement"
4
+ :is="resolvedElement"
5
5
  :class="[
6
6
  {
7
7
  'list-ordered' : ordered,
@@ -18,7 +18,8 @@
18
18
  :start="start"
19
19
  >
20
20
  <template v-if="items !== undefined">
21
- <li
21
+ <component
22
+ :is="itemElement"
22
23
  v-for="(item, index) in items"
23
24
  :key="index"
24
25
  :class="[
@@ -29,9 +30,9 @@
29
30
  <slot :item="item" :index="index">
30
31
  {{ item }}
31
32
  </slot>
32
- </li>
33
+ </component>
33
34
  </template>
34
- <slot v-else></slot>
35
+ <slot v-else />
35
36
  </component>
36
37
  </template>
37
38
 
@@ -45,7 +46,7 @@
45
46
  */
46
47
  items: Array,
47
48
  /**
48
- * Classes object (keys are { list, item } to be applied to <ul> and <li>)
49
+ * Classes object (keys are { list, item } to be applied to list and item elements)
49
50
  * - Any valid class binding for each
50
51
  */
51
52
  classes: {
@@ -85,10 +86,24 @@
85
86
  * Define list style type (ie. disc, decimal, etc)
86
87
  */
87
88
  listStyleType: String,
89
+ /**
90
+ * Element to render the list as (overrides ul/ol)
91
+ */
92
+ element: String,
93
+ /**
94
+ * Element to render items as when using items array
95
+ */
96
+ itemElement: {
97
+ type: String,
98
+ default: "li"
99
+ }
88
100
  });
89
101
 
90
- provide("uluListClasses", computed(() => props.classes));
102
+ provide("uluListContext", computed(() => ({
103
+ classes: props.classes,
104
+ itemElement: props.itemElement
105
+ })));
91
106
 
92
107
  const isOrdered = computed(() => props.ordered || props.forceOrdered);
93
- const listElement = computed(() => isOrdered.value ? "ol" : "ul");
94
- </script>
108
+ const resolvedElement = computed(() => props.element || (isOrdered.value ? "ol" : "ul"));
109
+ </script>
@@ -1,19 +1,24 @@
1
1
  <template>
2
- <li :class="[listClasses.item, classes]">
2
+ <component :is="resolvedElement" :class="[listClasses.item, classes]">
3
3
  <slot></slot>
4
- </li>
4
+ </component>
5
5
  </template>
6
6
 
7
7
  <script setup>
8
8
  import { computed, inject } from "vue";
9
9
 
10
- defineProps({
10
+ const props = defineProps({
11
11
  /**
12
12
  * Optional class binding to append to the injected parent classes
13
13
  */
14
- classes: [String, Array, Object]
14
+ classes: [String, Array, Object],
15
+ /**
16
+ * The HTML element to render the item as
17
+ */
18
+ element: String
15
19
  });
16
20
 
17
- const injectedClasses = inject("uluListClasses", { value: {} });
18
- const listClasses = computed(() => injectedClasses.value || {});
21
+ const injectedContext = inject("uluListContext", { value: {} });
22
+ const listClasses = computed(() => injectedContext.value?.classes || {});
23
+ const resolvedElement = computed(() => props.element || injectedContext.value?.itemElement || "li");
19
24
  </script>
@@ -0,0 +1,217 @@
1
+ <template>
2
+ <table :class="classes?.table">
3
+ <template v-if="columns && rows">
4
+ <caption v-if="caption || $slots.caption" :class="classes?.caption">
5
+ <slot name="caption">{{ caption }}</slot>
6
+ </caption>
7
+ <thead :class="classes?.thead">
8
+ <tr
9
+ v-for="(row, rowIndex) in headerRows"
10
+ :key="`hr-${rowIndex}`"
11
+ :class="resolveClasses(classes?.rowHeader, { row, rowIndex })"
12
+ >
13
+ <th
14
+ v-for="(column, colIndex) in row.columns"
15
+ :key="`hc-${colIndex}`"
16
+ :id="column.id"
17
+ :rowspan="column.rowspan"
18
+ :colspan="column.colspan"
19
+ :class="resolveClasses(column.classHeader, { column, index: colIndex })"
20
+ :scope="column.colspan > 1 ? 'colgroup' : 'col'"
21
+ :headers="getHeaderHeaders(column)"
22
+ >
23
+ <template v-if="$slots[column.slotHeader]">
24
+ <slot :name="column.slotHeader" :column="column" :index="colIndex"></slot>
25
+ </template>
26
+ <div v-else-if="column.htmlTitle" v-html="getColumnTitle({ column, index: colIndex })"></div>
27
+ <template v-else>{{ getColumnTitle({ column, index: colIndex }) }}</template>
28
+ </th>
29
+ </tr>
30
+ </thead>
31
+ <tbody :class="classes?.tbody">
32
+ <tr
33
+ v-for="(row, rowIndex) in currentRows"
34
+ :key="`br-${rowIndex}`"
35
+ :id="row.id"
36
+ :class="resolveClasses(classes?.row, { row: row.data, rowIndex })"
37
+ >
38
+ <component
39
+ v-for="(column, colIndex) in rowColumns"
40
+ :key="`bc-${colIndex}`"
41
+ :is="column.rowHeader ? 'th' : 'td'"
42
+ :id="column.rowHeader ? column.getRowHeaderId(rowIndex) : undefined"
43
+ :scope="column.rowHeader ? 'row' : undefined"
44
+ :headers="getCellHeaders(column, rowIndex)"
45
+ :class="resolveClasses(column.class, { column, index: colIndex, row, rowIndex })"
46
+ >
47
+ <template v-if="$slots[column.slot]">
48
+ <slot
49
+ :name="column.slot"
50
+ :row="row.data"
51
+ :column="column"
52
+ :rowIndex="rowIndex"
53
+ :index="colIndex"
54
+ />
55
+ </template>
56
+ <div
57
+ v-else-if="column.html"
58
+ v-html="getValue({ row, column, rowIndex })"
59
+ ></div>
60
+ <template v-else>
61
+ {{ getValue({ row, column, rowIndex }) }}
62
+ </template>
63
+ </component>
64
+ </tr>
65
+ </tbody>
66
+ <tfoot v-if="currentFooterRows.length" :class="classes?.tfoot">
67
+ <tr
68
+ v-for="(row, rowIndex) in currentFooterRows"
69
+ :key="`fr-${rowIndex}`"
70
+ :id="row.id"
71
+ :class="resolveClasses(classes?.rowFooter, { row: row.data, rowIndex })"
72
+ >
73
+ <component
74
+ v-for="(column, colIndex) in rowColumns"
75
+ :key="`fc-${colIndex}`"
76
+ :is="column.rowHeader ? 'th' : 'td'"
77
+ :id="column.rowHeader ? column.getRowHeaderId(rowIndex) : undefined"
78
+ :scope="column.rowHeader ? 'row' : undefined"
79
+ :headers="getCellHeaders(column, rowIndex)"
80
+ :class="resolveClasses(column.class, { column, index: colIndex, row, rowIndex })"
81
+ >
82
+ <template v-if="$slots[column.slot]">
83
+ <slot
84
+ :name="column.slot"
85
+ :row="row.data"
86
+ :column="column"
87
+ :rowIndex="rowIndex"
88
+ :index="colIndex"
89
+ />
90
+ </template>
91
+ <div
92
+ v-else-if="column.html"
93
+ v-html="getValue({ row, column, rowIndex })"
94
+ ></div>
95
+ <template v-else>
96
+ {{ getValue({ row, column, rowIndex }) }}
97
+ </template>
98
+ </component>
99
+ </tr>
100
+ </tfoot>
101
+ </template>
102
+ <slot v-else />
103
+ </table>
104
+ </template>
105
+
106
+ <script setup>
107
+ import { isArrayOfObjects } from "../../utils/props.js";
108
+ import { useTableData } from "../../composables/useTableData.js";
109
+
110
+ const props = defineProps({
111
+ /**
112
+ * Array of column configurations to convert to list output
113
+ *
114
+ * @property {Object} column A column config
115
+ * @property {String|Boolean} column.title The title to output for the column if set to a falsey value nothing will print
116
+ * @property {Array} column.columns Array of child columns
117
+ * @property {String} column.key The key that should be usec to grab column's value from rows
118
+ * @property {Function} column.value A function that returns the column's value used instead of key passed (row, column)
119
+ * @property {String} column.slot Register custom slot name to use as a template for this column. Passing a slot with this name will link them. The slot are passed the ({row, column}). Note this will disable output of the column's value
120
+ * @property {String} column.slotHeader Register custom slot name to use in the header
121
+ * @property {String} column.classHeader Custom class(s) to be set to column <th>
122
+ * @property {String} column.class Custom class(s) to be set to column's value <td>
123
+ * @property {String} column.html Use v-html output for value
124
+ * @property {String} column.rowHeader When this column is printed in the <tbody> it should be a header for the row. Note supports multiple row headers from left to right only. No rowspan support for rowHeaders.
125
+ */
126
+ columns: {
127
+ type: Array,
128
+ validator: isArrayOfObjects
129
+ },
130
+ /**
131
+ * Array of tables rows (tbody)
132
+ * - Each row is an object who's value will be matched to columns
133
+ */
134
+ rows: {
135
+ type: Array,
136
+ validator: isArrayOfObjects
137
+ },
138
+ /**
139
+ * Array of rows for footer (tfoot)
140
+ */
141
+ footerRows: {
142
+ type: Array,
143
+ validator: isArrayOfObjects
144
+ },
145
+ /**
146
+ * Hidden caption for accessibility (or visible depending on styles). Can also be passed via slot.
147
+ */
148
+ caption: String,
149
+ /**
150
+ * Allows user to pass classes object to add custom classes to parts of the component
151
+ */
152
+ classes: {
153
+ type: Object,
154
+ default: () => ({})
155
+ },
156
+ /**
157
+ * Prefix used for id generation
158
+ */
159
+ idPrefix: {
160
+ type: String,
161
+ default: "table"
162
+ },
163
+ /**
164
+ * Optional user overridden value getter (for rows)
165
+ * @param {Object} row The current row
166
+ * @param {Object} column The current column in the row
167
+ */
168
+ getRowValue: {
169
+ type: Function,
170
+ default: ({ row, column }) => row[column.key]
171
+ },
172
+ /**
173
+ * Optional user overridden title getter (for headers)
174
+ * @param {Object} column The current column
175
+ */
176
+ getColumnTitle: {
177
+ type: Function,
178
+ default: ({ column }) => column.title
179
+ }
180
+ });
181
+
182
+ const {
183
+ currentRows,
184
+ currentFooterRows,
185
+ headerRows,
186
+ rowColumns
187
+ } = useTableData(props);
188
+
189
+ const resolveClasses = (passed, args = null) => {
190
+ if (typeof passed === "undefined") return;
191
+ if (typeof passed === "function") return passed(args);
192
+ return passed;
193
+ };
194
+
195
+ const getHeaderHeaders = (column) => {
196
+ const headersArray = column.headers.filter(id => id !== column.id);
197
+ if (headersArray.length) {
198
+ return headersArray.join(" ");
199
+ }
200
+ };
201
+
202
+ const getCellHeaders = (column, rowIndex) => {
203
+ const headers = column.headers.join(" ");
204
+ const rowHeaders = column.getRowHeaders(rowIndex);
205
+ const s = rowHeaders.length ? " " : "";
206
+ return `${ headers }${ s }${ rowHeaders }`;
207
+ };
208
+
209
+ const getValue = ({ row, column, rowIndex }) => {
210
+ const valueFn = column.value;
211
+ if (valueFn) {
212
+ return valueFn({ row: row.data, column, rowIndex });
213
+ } else {
214
+ return props.getRowValue({ row: row.data, column, rowIndex });
215
+ }
216
+ };
217
+ </script>
@@ -22,6 +22,7 @@ export { default as UluButtonVerbose } from './elements/UluButtonVerbose.vue';
22
22
  export { default as UluCallout } from './elements/UluCallout.vue';
23
23
  export { default as UluCaptionedFigure } from './elements/UluCaptionedFigure.vue';
24
24
  export { default as UluCard } from './elements/UluCard.vue';
25
+ export { default as UluDataTable } from './elements/UluDataTable.vue';
25
26
  export { default as UluDefinitionList } from './elements/UluDefinitionList.vue';
26
27
  export { default as UluDefinitionListItem } from './elements/UluDefinitionListItem.vue';
27
28
  export { default as UluExternalLink } from './elements/UluExternalLink.vue';
@@ -33,12 +34,14 @@ export { default as UluImage } from './elements/UluImage.vue';
33
34
 
34
35
  export { default as UluList } from './elements/UluList.vue';
35
36
  export { default as UluListItem } from './elements/UluListItem.vue';
37
+ export { default as UluCounterList } from './elements/UluCounterList.vue';
36
38
  export { default as UluMain } from './elements/UluMain.vue';
37
39
  export { default as UluOverflowScroller } from './elements/UluOverflowScroller.vue';
38
40
  export { default as UluRule } from './elements/UluRule.vue';
39
41
  export { default as UluScrollSlider } from './elements/UluScrollSlider.vue';
40
42
  export { default as UluSlider } from './elements/UluSlider.vue';
41
43
  export { default as UluSpokeSpinner } from './elements/UluSpokeSpinner.vue';
44
+ export { default as UluTable } from './elements/UluTable.vue';
42
45
  export { default as UluTag } from './elements/UluTag.vue';
43
46
  export { default as UluSelectableMenu } from './forms/UluSelectableMenu.vue';
44
47
  export { default as UluFileDisplay } from './forms/UluFileDisplay.vue';