@katlux/preset-modern 0.1.1-alpha.91 → 0.1.1-alpha.93

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/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@katlux/preset-modern",
3
3
  "configKey": "katluxTemplateModern",
4
- "version": "0.1.1-alpha.91",
4
+ "version": "0.1.1-alpha.93",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -4,16 +4,13 @@ type __VLS_Props = {
4
4
  bulkActions: IKDatatableAction[];
5
5
  selectedRows: any[];
6
6
  selectAll: boolean;
7
+ selected?: any;
7
8
  dp: CFlatClientDataProvider;
8
9
  doAction: (action: any) => void;
9
10
  };
10
- type __VLS_ModelProps = {
11
- 'selected'?: any;
12
- };
13
- type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
14
- declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
15
12
  "update:selected": (value: any) => any;
16
- }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
13
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
17
14
  "onUpdate:selected"?: ((value: any) => any) | undefined;
18
15
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
19
16
  declare const _default: typeof __VLS_export;
@@ -5,7 +5,7 @@
5
5
  template(v-if="bulkActions.length > 3")
6
6
  KCombobox(
7
7
  :dataProvider="dp"
8
- v-model="selected"
8
+ v-model="internalSelected"
9
9
  labelField="label"
10
10
  closeOnSelect
11
11
  :disabled="selectedRows.length === 0"
@@ -13,41 +13,48 @@
13
13
  class="action-select"
14
14
  )
15
15
  KButton(
16
- @click="doAction(selected)"
16
+ @click="doAction(internalSelected)"
17
17
  size="small"
18
- :disabled="selectedRows.length === 0 || selected == undefined"
18
+ :disabled="selectedRows.length === 0 || internalSelected == undefined"
19
19
  class="execute-btn"
20
20
  ) {{ t('Apply') }}
21
21
 
22
22
  template(v-else v-for="action in bulkActions" :key="action.label")
23
23
  KTooltip(
24
24
  :text="action.label"
25
- :disabled="!(action.iconOnly || !!action.icon)"
25
+ :disabled="!action.iconOnly"
26
26
  )
27
27
  KButton(
28
28
  @click="doAction(action)"
29
29
  size="small"
30
30
  :type="action.type || 'default'"
31
- :iconOnly="action.iconOnly || !!action.icon"
31
+ :iconOnly="action.iconOnly"
32
+ :disabled="selectedRows.length === 0"
32
33
  class="action-btn"
33
34
  )
34
35
  template(#icon v-if="action.icon")
35
36
  KIcon(:iconname="action.icon" :width="16" :height="16")
36
- template(#default v-if="!action.iconOnly && !action.icon") {{ action.label }}
37
+ template(#default v-if="!action.iconOnly") {{ action.label }}
37
38
  </template>
38
39
 
39
40
  <script setup>
41
+ import { computed } from "vue";
40
42
  import { CFlatClientDataProvider } from "@katlux/providers";
41
- const nuxtApp = useNuxtApp?.();
42
- const t = (key) => nuxtApp?.$t ? nuxtApp.$t(key) : key;
43
- const selected = defineModel("selected", { type: null });
44
- defineProps({
43
+ import { useKatluxI18n } from "#toolkit/composables/useKatluxI18n";
44
+ const { t } = useKatluxI18n();
45
+ const props = defineProps({
45
46
  bulkActions: { type: Array, required: true },
46
47
  selectedRows: { type: Array, required: true },
47
48
  selectAll: { type: Boolean, required: true },
49
+ selected: { type: null, required: false },
48
50
  dp: { type: Object, required: true },
49
51
  doAction: { type: Function, required: true }
50
52
  });
53
+ const emit = defineEmits(["update:selected"]);
54
+ const internalSelected = computed({
55
+ get: () => props.selected,
56
+ set: (val) => emit("update:selected", val)
57
+ });
51
58
  </script>
52
59
 
53
60
  <style scoped>
@@ -60,6 +67,9 @@ defineProps({
60
67
  gap: var(--gap-sm);
61
68
  align-items: center;
62
69
  }
70
+ .k-bulk-actions-modern .action-select {
71
+ min-width: 180px;
72
+ }
63
73
  .k-bulk-actions-modern .action-btn {
64
74
  border-radius: var(--border-radius-sm);
65
75
  font-weight: var(--font-weight-medium);
@@ -4,16 +4,13 @@ type __VLS_Props = {
4
4
  bulkActions: IKDatatableAction[];
5
5
  selectedRows: any[];
6
6
  selectAll: boolean;
7
+ selected?: any;
7
8
  dp: CFlatClientDataProvider;
8
9
  doAction: (action: any) => void;
9
10
  };
10
- type __VLS_ModelProps = {
11
- 'selected'?: any;
12
- };
13
- type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
14
- declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
15
12
  "update:selected": (value: any) => any;
16
- }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
13
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
17
14
  "onUpdate:selected"?: ((value: any) => any) | undefined;
18
15
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
19
16
  declare const _default: typeof __VLS_export;
@@ -1,7 +1,13 @@
1
1
  <template lang="pug">
2
2
  .KCheckbox-wrapper
3
- label.KCheckbox.modern-checkbox
4
- input(type="checkbox" v-model="formattedModel" :value="checkboxValue" :disabled="isDisabled")
3
+ label.KCheckbox.modern-checkbox(
4
+ role="checkbox"
5
+ :aria-checked="isChecked"
6
+ :aria-disabled="isDisabled"
7
+ tabindex="0"
8
+ @keydown.space.prevent="handleSpace"
9
+ )
10
+ input(type="checkbox" v-model="formattedModel" :value="checkboxValue" :disabled="isDisabled" tabindex="-1")
5
11
  .checkbox-box(:class="validation ? `is-${validation}` : ''")
6
12
  .checkbox-checkmark
7
13
  KIcon.icon(iconname="check")
@@ -27,6 +33,42 @@ const formattedModel = computed({
27
33
  get: () => props.model,
28
34
  set: (value) => emit("update:model", value)
29
35
  });
36
+ const findModelIndex = (arr, value) => {
37
+ const refIdx = arr.indexOf(value);
38
+ if (refIdx > -1) return refIdx;
39
+ if (value && typeof value === "object") {
40
+ const valId = value.id ?? value._id ?? value.key ?? value.value;
41
+ if (valId !== void 0 && valId !== null) {
42
+ return arr.findIndex((item) => {
43
+ if (!item || typeof item !== "object") return false;
44
+ const itemId = item.id ?? item._id ?? item.key ?? item.value;
45
+ return itemId === valId;
46
+ });
47
+ }
48
+ }
49
+ return -1;
50
+ };
51
+ const isChecked = computed(() => {
52
+ if (Array.isArray(formattedModel.value)) {
53
+ return findModelIndex(formattedModel.value, props.checkboxValue) > -1;
54
+ }
55
+ return !!formattedModel.value;
56
+ });
57
+ const handleSpace = () => {
58
+ if (props.isDisabled) return;
59
+ if (Array.isArray(formattedModel.value)) {
60
+ const idx = findModelIndex(formattedModel.value, props.checkboxValue);
61
+ if (idx > -1) {
62
+ const updated = [...formattedModel.value];
63
+ updated.splice(idx, 1);
64
+ formattedModel.value = updated;
65
+ } else {
66
+ formattedModel.value = [...formattedModel.value, props.checkboxValue];
67
+ }
68
+ } else {
69
+ formattedModel.value = !formattedModel.value;
70
+ }
71
+ };
30
72
  </script>
31
73
 
32
74
  <style scoped>
@@ -2,9 +2,11 @@ import { ADataProvider } from '@katlux/providers';
2
2
  import type { IKDatatableAction } from '@katlux/providers';
3
3
  type __VLS_Props = {
4
4
  dataProvider: ADataProvider;
5
- visibleFields: Array<string> | null;
6
- rowActions: Array<IKDatatableAction>;
7
- bulkActions: Array<IKDatatableAction>;
5
+ visibleFields?: Array<string> | null;
6
+ rowActions?: Array<IKDatatableAction>;
7
+ bulkActions?: Array<IKDatatableAction>;
8
+ selectedRows?: any[];
9
+ selectAll?: boolean;
8
10
  cellSlots?: Record<string, any>;
9
11
  headerSlots?: Record<string, any>;
10
12
  columnHeaders?: Record<string, string>;
@@ -12,17 +14,24 @@ type __VLS_Props = {
12
14
  emptyStateText?: string;
13
15
  emptyFilterStateText?: string;
14
16
  };
15
- type __VLS_ModelProps = {
16
- 'selectedRows'?: any[];
17
- 'selectAll'?: boolean;
18
- };
19
- type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
20
- declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
17
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
21
18
  "update:selectedRows": (value: any[]) => any;
22
19
  "update:selectAll": (value: boolean) => any;
23
- }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
20
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
24
21
  "onUpdate:selectedRows"?: ((value: any[]) => any) | undefined;
25
22
  "onUpdate:selectAll"?: ((value: boolean) => any) | undefined;
26
- }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
23
+ }>, {
24
+ bulkActions: Array<IKDatatableAction>;
25
+ selectedRows: any[];
26
+ selectAll: boolean;
27
+ visibleFields: Array<string> | null;
28
+ rowActions: Array<IKDatatableAction>;
29
+ cellSlots: Record<string, any>;
30
+ headerSlots: Record<string, any>;
31
+ columnHeaders: Record<string, string>;
32
+ columnWidths: Record<string, string>;
33
+ emptyStateText: string;
34
+ emptyFilterStateText: string;
35
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
27
36
  declare const _default: typeof __VLS_export;
28
37
  export default _default;
@@ -1,74 +1,103 @@
1
1
  <template lang="pug">
2
- .k-datatable.modern-datatable(:style="{ '--page-size': dataProvider?.pageSize?.value || 10 }" role="region" :aria-label="t('Data Table')")
3
- .header(v-if="bulkActions && bulkActions.length > 0 && selectedRows.length > 0")
4
- .selected-count {{ t('{count} items selected').replace('{count}', selectedRows.length.toString()) }}
5
- KBulkActions.bulk-actions(:bulkActions="bulkActions" :selectedRows="selectedRows" :selectAll="selectAll")
2
+ .k-datatable.modern-datatable(:style="{ '--page-size': dpPageSize || 10 }" role="region" :aria-label="t('Data Table')")
3
+ .header(v-if="props.bulkActions && props.bulkActions.length > 0 && selectedRows.length > 0")
4
+ .selected-count {{ t('{count} items selected').replace('{count}', (selectedRows?.length || 0).toString()) }}
5
+ KBulkActions.bulk-actions(:bulkActions="props.bulkActions" :selectedRows="selectedRows" :selectAll="selectAll")
6
6
 
7
7
  .k-datatable-wrapper
8
- .loading-overlay(v-if="dataProvider.loading.value")
8
+ .loading-overlay(v-if="isLoading")
9
9
  .spinner
10
10
 
11
- table(role="grid" :aria-busy="dataProvider.loading.value")
11
+ table(role="grid" :aria-busy="isLoading")
12
12
  thead
13
13
  tr
14
- th.check-cell(v-if="bulkActions && bulkActions.length > 0")
14
+ th.check-cell(v-if="props.bulkActions && props.bulkActions.length > 0")
15
15
  KCheckbox(v-model="selectAll")
16
- th(v-for="field in visibleFields || dataProvider.fields" :key="field" :data-field="field" :style="getColumnStyle(field)")
16
+ th(v-for="field in visibleFields || props.dataProvider.fields" :key="field" :data-field="field" :style="getColumnStyle(field)")
17
17
  component(v-if="getHeaderSlot(field)" :is="getHeaderSlot(field)" :field="field")
18
18
  span(v-else) {{ columnHeaders?.[field] ?? field }}
19
- th.actions-cell(v-if="rowActions && rowActions.length > 0") {{ t('Actions') }}
19
+ th.actions-cell(v-if="props.rowActions && props.rowActions.length > 0") {{ t('Actions') }}
20
20
 
21
21
  tbody
22
- tr.empty-row(v-if="!dataProvider.loading.value && (!dataProvider.pageData.value || dataProvider.pageData.value.length === 0)")
23
- td.empty-state(:colspan="(visibleFields || dataProvider.fields || []).length + (bulkActions && bulkActions.length > 0 ? 1 : 0) + (rowActions && rowActions.length > 0 ? 1 : 0)")
24
- span(v-if="dataProvider.filter.value?.active") {{ emptyFilterStateText || t('No result found for filter') }}
25
- span(v-else) {{ emptyStateText || t('No result') }}
26
- tr(v-for="(row, index) in dataProvider.pageData.value" :key="index" :class="{ 'selected': selectedRows.includes(row) }")
27
- td.check-cell(v-if="bulkActions && bulkActions.length > 0")
22
+ tr.empty-row(v-if="!isLoading && (!pageRows || pageRows.length === 0)")
23
+ td.empty-state(:colspan="(visibleFields || props.dataProvider.fields || []).length + (props.bulkActions && props.bulkActions.length > 0 ? 1 : 0) + (props.rowActions && props.rowActions.length > 0 ? 1 : 0)")
24
+ span(v-if="dpFilter?.active || props.dataProvider.filter?.value?.active") {{ props.emptyFilterStateText || t('No result found for filter') }}
25
+ span(v-else) {{ props.emptyStateText || t('No result') }}
26
+ tr(v-for="(row, index) in pageRows" :key="getRowKey(row, index)" :class="{ 'selected': isRowSelected(row) }")
27
+ td.check-cell(v-if="props.bulkActions && props.bulkActions.length > 0")
28
28
  KCheckbox(:value="row" v-model="selectedRows")
29
- td(v-for="visibleField in visibleFields || dataProvider.fields" :key="visibleField" :data-field="visibleField" :style="getColumnStyle(visibleField)")
29
+ td(v-for="visibleField in visibleFields || props.dataProvider.fields" :key="visibleField" :data-field="visibleField" :style="getColumnStyle(visibleField)")
30
30
  component(v-if="getCellSlot(visibleField)" :is="getCellSlot(visibleField)" :row="row" :field="visibleField" :value="row[visibleField]")
31
31
  span(v-else) {{ row[visibleField] }}
32
- td.actions-cell(v-if="rowActions && rowActions.length > 0")
32
+ td.actions-cell(v-if="props.rowActions && props.rowActions.length > 0")
33
33
  .action-buttons
34
- KTooltip(
35
- v-for="rowAction in rowActions"
36
- :key="rowAction.label"
37
- :text="rowAction.label"
38
- :disabled="!(rowAction.iconOnly || !!rowAction.icon)"
39
- )
40
- KButton.action-btn(
41
- :type="rowAction.type || 'default'"
42
- :iconOnly="rowAction.iconOnly || !!rowAction.icon"
43
- size="small"
44
- @click="rowAction.action(row)"
34
+ template(v-for="rowAction in props.rowActions" :key="rowAction.label")
35
+ KTooltip(
36
+ v-if="!rowAction.visible || rowAction.visible(row)"
37
+ :text="rowAction.label"
38
+ :disabled="!rowAction.iconOnly"
45
39
  )
46
- template(#icon v-if="rowAction.icon")
47
- KIcon(:iconname="rowAction.icon" :width="16" :height="16")
48
- template(#default v-if="!rowAction.iconOnly && !rowAction.icon") {{ rowAction.label }}
40
+ KButton.action-btn(
41
+ :type="rowAction.type || 'default'"
42
+ :iconOnly="rowAction.iconOnly"
43
+ size="small"
44
+ @click="rowAction.action(row)"
45
+ )
46
+ template(#icon v-if="rowAction.icon")
47
+ KIcon(:iconname="rowAction.icon" :width="16" :height="16")
48
+ template(#default v-if="!rowAction.iconOnly") {{ rowAction.label }}
49
49
 
50
50
  .footer
51
- KPagination.pagination(:dataProvider="dataProvider")
51
+ KPagination.pagination(:dataProvider="props.dataProvider")
52
52
  </template>
53
53
 
54
54
  <script setup>
55
+ import { computed } from "vue";
55
56
  import { ADataProvider } from "@katlux/providers";
56
- const nuxtApp = useNuxtApp?.();
57
- const t = (key) => nuxtApp?.$t ? nuxtApp.$t(key) : key;
58
- const selectedRows = defineModel("selectedRows", { type: Array, ...{ default: () => [] } });
59
- const selectAll = defineModel("selectAll", { type: Boolean, ...{ default: false } });
57
+ import { useKatluxI18n } from "#toolkit/composables/useKatluxI18n";
58
+ import { useDataProvider } from "#toolkit/composables/useDataProvider";
59
+ const { t } = useKatluxI18n();
60
60
  const props = defineProps({
61
61
  dataProvider: { type: Object, required: true },
62
- visibleFields: { type: [Array, null], required: true },
63
- rowActions: { type: Array, required: true },
64
- bulkActions: { type: Array, required: true },
65
- cellSlots: { type: Object, required: false },
66
- headerSlots: { type: Object, required: false },
67
- columnHeaders: { type: Object, required: false },
68
- columnWidths: { type: Object, required: false },
69
- emptyStateText: { type: String, required: false },
70
- emptyFilterStateText: { type: String, required: false }
62
+ visibleFields: { type: [Array, null], required: false, default: null },
63
+ rowActions: { type: Array, required: false, default: () => [] },
64
+ bulkActions: { type: Array, required: false, default: () => [] },
65
+ selectedRows: { type: Array, required: false, default: () => [] },
66
+ selectAll: { type: Boolean, required: false, default: false },
67
+ cellSlots: { type: Object, required: false, default: void 0 },
68
+ headerSlots: { type: Object, required: false, default: void 0 },
69
+ columnHeaders: { type: Object, required: false, default: void 0 },
70
+ columnWidths: { type: Object, required: false, default: void 0 },
71
+ emptyStateText: { type: String, required: false, default: "" },
72
+ emptyFilterStateText: { type: String, required: false, default: "" }
71
73
  });
74
+ const emit = defineEmits(["update:selectedRows", "update:selectAll"]);
75
+ const selectedRows = computed({
76
+ get: () => props.selectedRows || [],
77
+ set: (val) => emit("update:selectedRows", val)
78
+ });
79
+ const selectAll = computed({
80
+ get: () => props.selectAll || false,
81
+ set: (val) => emit("update:selectAll", val)
82
+ });
83
+ const getRowKey = (row, index) => {
84
+ const idKey = props.dataProvider?.idKey || "id";
85
+ if (row && row[idKey] !== void 0 && row[idKey] !== null) {
86
+ return row[idKey];
87
+ }
88
+ if (row && row.id !== void 0 && row.id !== null) {
89
+ return row.id;
90
+ }
91
+ if (row && row._id !== void 0 && row._id !== null) {
92
+ return row._id;
93
+ }
94
+ return index;
95
+ };
96
+ const isRowSelected = (row) => {
97
+ const idKey = props.dataProvider?.idKey || "id";
98
+ const rowId = row?.[idKey] ?? row?.id ?? row?._id ?? row;
99
+ return (selectedRows.value || []).some((r) => (r?.[idKey] ?? r?.id ?? r?._id ?? r) === rowId || r === row);
100
+ };
72
101
  const getCellSlot = (fieldName) => {
73
102
  const slotName = "cell-" + fieldName;
74
103
  return props.cellSlots?.[slotName];
@@ -82,6 +111,11 @@ const getColumnStyle = (field) => {
82
111
  if (!w) return void 0;
83
112
  return { width: w, whiteSpace: "nowrap" };
84
113
  };
114
+ const { pageData, filter: dpFilter, loading: dpLoading, initialLoad: dpInitialLoad, pageSize: dpPageSize } = useDataProvider(props.dataProvider);
115
+ const pageRows = computed(() => pageData.value || []);
116
+ const isLoading = computed(() => {
117
+ return dpLoading.value || dpInitialLoad.value || false;
118
+ });
85
119
  </script>
86
120
 
87
121
  <style scoped>
@@ -151,6 +185,8 @@ const getColumnStyle = (field) => {
151
185
  text-align: center;
152
186
  }
153
187
  .modern-datatable table thead th.actions-cell {
188
+ width: 1%;
189
+ white-space: nowrap;
154
190
  text-align: right;
155
191
  }
156
192
  .modern-datatable table tbody tr {
@@ -166,6 +202,8 @@ const getColumnStyle = (field) => {
166
202
  text-align: center;
167
203
  }
168
204
  .modern-datatable table tbody tr td.actions-cell {
205
+ width: 1%;
206
+ white-space: nowrap;
169
207
  text-align: right;
170
208
  }
171
209
  .modern-datatable table tbody tr td.empty-state {
@@ -2,9 +2,11 @@ import { ADataProvider } from '@katlux/providers';
2
2
  import type { IKDatatableAction } from '@katlux/providers';
3
3
  type __VLS_Props = {
4
4
  dataProvider: ADataProvider;
5
- visibleFields: Array<string> | null;
6
- rowActions: Array<IKDatatableAction>;
7
- bulkActions: Array<IKDatatableAction>;
5
+ visibleFields?: Array<string> | null;
6
+ rowActions?: Array<IKDatatableAction>;
7
+ bulkActions?: Array<IKDatatableAction>;
8
+ selectedRows?: any[];
9
+ selectAll?: boolean;
8
10
  cellSlots?: Record<string, any>;
9
11
  headerSlots?: Record<string, any>;
10
12
  columnHeaders?: Record<string, string>;
@@ -12,17 +14,24 @@ type __VLS_Props = {
12
14
  emptyStateText?: string;
13
15
  emptyFilterStateText?: string;
14
16
  };
15
- type __VLS_ModelProps = {
16
- 'selectedRows'?: any[];
17
- 'selectAll'?: boolean;
18
- };
19
- type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
20
- declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
17
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
21
18
  "update:selectedRows": (value: any[]) => any;
22
19
  "update:selectAll": (value: boolean) => any;
23
- }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
20
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
24
21
  "onUpdate:selectedRows"?: ((value: any[]) => any) | undefined;
25
22
  "onUpdate:selectAll"?: ((value: boolean) => any) | undefined;
26
- }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
23
+ }>, {
24
+ bulkActions: Array<IKDatatableAction>;
25
+ selectedRows: any[];
26
+ selectAll: boolean;
27
+ visibleFields: Array<string> | null;
28
+ rowActions: Array<IKDatatableAction>;
29
+ cellSlots: Record<string, any>;
30
+ headerSlots: Record<string, any>;
31
+ columnHeaders: Record<string, string>;
32
+ columnWidths: Record<string, string>;
33
+ emptyStateText: string;
34
+ emptyFilterStateText: string;
35
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
27
36
  declare const _default: typeof __VLS_export;
28
37
  export default _default;
@@ -4,6 +4,8 @@ type __VLS_Props = {
4
4
  placeholder: string;
5
5
  showClear: boolean;
6
6
  mask: string;
7
+ validation?: 'success' | 'warning' | 'error' | null;
8
+ validationText?: string;
7
9
  };
8
10
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
9
11
  "update:maskedValue": (value: string) => any;
@@ -5,7 +5,10 @@
5
5
  :modelValue="maskedValue"
6
6
  :placeholder="placeholder"
7
7
  :showClear="showClear"
8
+ :clear="handleClear"
8
9
  :maxlength="mask.length"
10
+ :validation="validation"
11
+ :validationText="validationText"
9
12
  @update:modelValue="handleUpdate"
10
13
  @beforeinput="handleBeforeInput"
11
14
  )
@@ -13,13 +16,15 @@
13
16
 
14
17
  <script setup>
15
18
  import { computed } from "vue";
16
- import { getMaskPatternDef } from "@katlux/toolkit/components/KMaskTextbox/KMaskTextbox.logic";
19
+ import { getMaskPatternDef } from "#toolkit/components/KMaskTextbox/KMaskTextbox.logic";
17
20
  const props = defineProps({
18
21
  label: { type: String, required: false },
19
22
  maskedValue: { type: String, required: true },
20
23
  placeholder: { type: String, required: true },
21
24
  showClear: { type: Boolean, required: true },
22
- mask: { type: String, required: true }
25
+ mask: { type: String, required: true },
26
+ validation: { type: [String, null], required: false },
27
+ validationText: { type: String, required: false }
23
28
  });
24
29
  const emit = defineEmits(["update:maskedValue", "clear"]);
25
30
  const handleBeforeInput = (event) => {
@@ -97,6 +102,9 @@ const handleBeforeInput = (event) => {
97
102
  const handleUpdate = (value) => {
98
103
  emit("update:maskedValue", value);
99
104
  };
105
+ const handleClear = () => {
106
+ emit("clear");
107
+ };
100
108
  </script>
101
109
 
102
110
  <style lang="scss" scoped>
@@ -4,6 +4,8 @@ type __VLS_Props = {
4
4
  placeholder: string;
5
5
  showClear: boolean;
6
6
  mask: string;
7
+ validation?: 'success' | 'warning' | 'error' | null;
8
+ validationText?: string;
7
9
  };
8
10
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
9
11
  "update:maskedValue": (value: string) => any;
@@ -1,56 +1,64 @@
1
1
  <template lang="pug">
2
- .k-pagination-modern(v-if="totalPages > 1")
3
- ul.pagination-list
4
- li
5
- KButton.nav-btn(
6
- :onClick="goToPrev"
7
- :isDisabled="!showPrevButton"
8
- :buttonClasses="['light', 'small']"
9
- :aria-label="t('Previous page')"
10
- ) ‹
2
+ nav.k-pagination-modern(v-if="totalPages > 1" :aria-label="t('Pagination Navigation')")
3
+ ul.pagination-list
4
+ li(v-if="showPrevButton")
5
+ KButton.nav-btn(
6
+ @click="goToPrev"
7
+ :disabled="!showPrevButton"
8
+ :href="getPageHref(dp.currentPage.value - 1)"
9
+ size="small"
10
+ type="light"
11
+ :aria-label="t('Previous Page')"
12
+ ) ‹
11
13
 
12
- li(v-if="showFirstEllipsis")
13
- KButton.page-btn(
14
- :onClick="goToFirst"
15
- :buttonClasses="['light', 'small']"
16
- :isLink="!!getPageHref(1)"
17
- :href="getPageHref(1)"
18
- ) 1
19
-
20
- li(v-if="showFirstEllipsis")
21
- span.ellipsis ...
14
+ li(v-if="showFirstEllipsis")
15
+ KButton.page-btn(
16
+ @click="goToFirst"
17
+ :href="getPageHref(1)"
18
+ size="small"
19
+ type="light"
20
+ :aria-label="t('Go to Page 1')"
21
+ ) 1
22
+
23
+ li(v-if="showFirstEllipsis")
24
+ span.ellipsis ...
22
25
 
23
- li(v-for="item in visiblePages" :key="item")
24
- KButton.page-btn(
25
- :onClick="() => pageClicked(item)"
26
- :buttonClasses="[item === dp.currentPage.value ? 'primary' : 'light', 'small']"
27
- :isLink="!!getPageHref(item)"
28
- :href="getPageHref(item)"
29
- ) {{ item }}
26
+ li(v-for="item in visiblePages" :key="item")
27
+ KButton.page-btn(
28
+ @click="() => pageClicked(item)"
29
+ :href="getPageHref(item)"
30
+ size="small"
31
+ :type="item === dp.currentPage.value ? 'primary' : 'light'"
32
+ :aria-current="item === dp.currentPage.value ? 'page' : undefined"
33
+ :aria-label="t('Page') + ' ' + item"
34
+ ) {{ item }}
30
35
 
31
- li(v-if="showLastEllipsis")
32
- span.ellipsis ...
36
+ li(v-if="showLastEllipsis")
37
+ span.ellipsis ...
33
38
 
34
- li(v-if="showLastEllipsis")
35
- KButton.page-btn(
36
- :onClick="goToLast"
37
- :buttonClasses="['light', 'small']"
38
- :isLink="!!getPageHref(totalPages)"
39
- :href="getPageHref(totalPages)"
40
- ) {{ totalPages }}
39
+ li(v-if="showLastEllipsis")
40
+ KButton.page-btn(
41
+ @click="goToLast"
42
+ :href="getPageHref(totalPages)"
43
+ size="small"
44
+ type="light"
45
+ :aria-label="t('Go to Page') + ' ' + totalPages"
46
+ ) {{ totalPages }}
41
47
 
42
- li
43
- KButton.nav-btn(
44
- :onClick="goToNext"
45
- :isDisabled="!showNextButton"
46
- :buttonClasses="['light', 'small']"
47
- :aria-label="t('Next page')"
48
- ) ›
48
+ li(v-if="showNextButton")
49
+ KButton.nav-btn(
50
+ @click="goToNext"
51
+ :disabled="!showNextButton"
52
+ :href="getPageHref(dp.currentPage.value + 1)"
53
+ size="small"
54
+ type="light"
55
+ :aria-label="t('Next Page')"
56
+ ) ›
49
57
  </template>
50
58
 
51
59
  <script setup>
52
- const nuxtApp = useNuxtApp?.();
53
- const t = (key) => nuxtApp?.$t ? nuxtApp.$t(key) : key;
60
+ import { useKatluxI18n } from "#toolkit/composables/useKatluxI18n";
61
+ const { t } = useKatluxI18n();
54
62
  defineProps({
55
63
  dp: { type: null, required: true },
56
64
  totalPages: { type: Number, required: true },
@@ -1,7 +1,13 @@
1
1
  <template lang="pug">
2
2
  .KRadiobox-wrapper
3
- label.KRadiobox.modern-radiobox
4
- input(type="radio" v-model="internalModel" :value="value" :disabled="disabled")
3
+ label.KRadiobox.modern-radiobox(
4
+ role="radio"
5
+ :aria-checked="internalModel === value"
6
+ :aria-disabled="disabled"
7
+ tabindex="0"
8
+ @keydown.space.prevent="internalModel = value"
9
+ )
10
+ input(type="radio" v-model="internalModel" :value="value" :disabled="disabled" tabindex="-1")
5
11
  .radiobox-box(:class="validation ? `is-${validation}` : ''")
6
12
  .radiobox-checkmark
7
13
  KIcon.icon(iconname="check")
@@ -2,6 +2,8 @@ type __VLS_Props = {
2
2
  placeholder: string;
3
3
  rows: number;
4
4
  label?: string;
5
+ validation?: 'success' | 'warning' | 'error' | null;
6
+ validationText?: string;
5
7
  };
6
8
  type __VLS_ModelProps = {
7
9
  'text'?: string;
@@ -1,15 +1,33 @@
1
1
  <template lang="pug">
2
- .KTextarea-wrapper
2
+ .KTextarea-wrapper(:class="$attrs.class" :style="$attrs.style")
3
3
  label.k-input-label(v-if="label") {{ label }}
4
- textarea.KTextarea.modern-textarea(v-model="text" :placeholder="placeholder" :rows="rows")
4
+ textarea.KTextarea.modern-textarea(
5
+ v-bind="textareaAttrs"
6
+ v-model="text"
7
+ :placeholder="placeholder"
8
+ :rows="rows"
9
+ :class="validation ? `is-${validation}` : ''"
10
+ )
11
+ span.validation-text(v-if="validation && ['success', 'warning', 'error'].includes(validation) && validationText" :class="`is-${validation}`") {{ validationText }}
5
12
  </template>
6
13
 
7
14
  <script setup>
15
+ import { useAttrs, computed } from "vue";
16
+ defineOptions({
17
+ inheritAttrs: false
18
+ });
8
19
  const text = defineModel("text", { type: String });
9
- defineProps({
20
+ const props = defineProps({
10
21
  placeholder: { type: String, required: true },
11
22
  rows: { type: Number, required: true },
12
- label: { type: String, required: false }
23
+ label: { type: String, required: false },
24
+ validation: { type: [String, null], required: false },
25
+ validationText: { type: String, required: false }
26
+ });
27
+ const attrs = useAttrs();
28
+ const textareaAttrs = computed(() => {
29
+ const { class: _, style: __, ...rest } = attrs;
30
+ return rest;
13
31
  });
14
32
  </script>
15
33
 
@@ -52,4 +70,36 @@ defineProps({
52
70
  color: var(--neutral-400);
53
71
  cursor: not-allowed;
54
72
  }
73
+ .KTextarea.modern-textarea.is-error {
74
+ border-color: var(--color-danger, #ef4444);
75
+ }
76
+ .KTextarea.modern-textarea.is-error:focus {
77
+ box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.2);
78
+ }
79
+ .KTextarea.modern-textarea.is-warning {
80
+ border-color: var(--color-warning, #f59e0b);
81
+ }
82
+ .KTextarea.modern-textarea.is-warning:focus {
83
+ box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.2);
84
+ }
85
+ .KTextarea.modern-textarea.is-success {
86
+ border-color: var(--color-success, #10b981);
87
+ }
88
+ .KTextarea.modern-textarea.is-success:focus {
89
+ box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.2);
90
+ }
91
+
92
+ .validation-text {
93
+ font-size: var(--font-size-xs, 12px);
94
+ margin-top: 4px;
95
+ }
96
+ .validation-text.is-error {
97
+ color: var(--color-danger, #ef4444);
98
+ }
99
+ .validation-text.is-warning {
100
+ color: var(--color-warning, #f59e0b);
101
+ }
102
+ .validation-text.is-success {
103
+ color: var(--color-success, #10b981);
104
+ }
55
105
  </style>
@@ -2,6 +2,8 @@ type __VLS_Props = {
2
2
  placeholder: string;
3
3
  rows: number;
4
4
  label?: string;
5
+ validation?: 'success' | 'warning' | 'error' | null;
6
+ validationText?: string;
5
7
  };
6
8
  type __VLS_ModelProps = {
7
9
  'text'?: string;
@@ -10,8 +10,8 @@
10
10
 
11
11
  <script setup>
12
12
  import { computed, useAttrs } from "vue";
13
- const nuxtApp = useNuxtApp?.();
14
- const t = (key) => nuxtApp?.$t ? nuxtApp.$t(key) : key;
13
+ import { useKatluxI18n } from "#toolkit/composables/useKatluxI18n";
14
+ const { t } = useKatluxI18n();
15
15
  defineOptions({
16
16
  inheritAttrs: false
17
17
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@katlux/preset-modern",
3
- "version": "0.1.1-alpha.91",
3
+ "version": "0.1.1-alpha.93",
4
4
  "description": "Modern default design preset and styling variables for Katlux components",
5
5
  "author": "Katlux",
6
6
  "license": "Apache-2.0",