@rotki/ui-library 3.1.0 → 3.1.1
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/components/alerts/RuiAlert.js.map +1 -1
- package/dist/components/alerts/RuiAlert.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/buttons/button/button-styles.js.map +1 -1
- package/dist/components/chips/RuiChip.js.map +1 -1
- package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/check-control-styles.js.map +1 -1
- package/dist/components/forms/file-upload/RuiFileUpload.js.map +1 -1
- package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js +8 -3
- package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/select/RuiMenuSelect.js.map +1 -1
- package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/text-area/text-area-styles.js +6 -6
- package/dist/components/forms/text-area/text-area-styles.js.map +1 -1
- package/dist/components/forms/text-field/text-field-styles.js +6 -6
- package/dist/components/forms/text-field/text-field-styles.js.map +1 -1
- package/dist/components/tables/RuiDataTable.js.map +1 -1
- package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiTableHead.js.map +1 -1
- package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableAppendRow.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableAppendRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table-styles.d.ts +2 -1
- package/dist/components/tables/data-table-styles.js +3 -2
- package/dist/components/tables/data-table-styles.js.map +1 -1
- package/dist/composables/forms/auto-complete/keyboard-navigation.js.map +1 -1
- package/dist/composables/tables/data-table/columns.js.map +1 -1
- package/dist/composables/tables/data-table/selection.js +23 -21
- package/dist/composables/tables/data-table/selection.js.map +1 -1
- package/dist/icons/icons_1.js.map +1 -1
- package/dist/icons/icons_2.js.map +1 -1
- package/dist/icons/icons_3.js.map +1 -1
- package/dist/icons/icons_4.js.map +1 -1
- package/dist/icons/icons_5.js.map +1 -1
- package/dist/style.css +50 -19
- package/dist/styles/colors.css +4 -0
- package/dist/theme/theme.css +1 -1
- package/dist/theme.css +1 -1
- package/dist/vite-plugin/types.d.ts +1 -1
- package/dist/web-types.json +1 -1
- package/package.json +1 -1
|
@@ -68,6 +68,27 @@ function useTableSelection(options, deps) {
|
|
|
68
68
|
else if (!checked && selected) set(internalSelectedData, selectedRows.filter((r) => r !== value));
|
|
69
69
|
if (userAction) set(selectedData, get(internalSelectedData));
|
|
70
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Checks or unchecks every selectable row from `from` to `to`, updating the selection once.
|
|
73
|
+
*/
|
|
74
|
+
function selectRange(from, to, checked) {
|
|
75
|
+
const tableData = get(filtered);
|
|
76
|
+
const currentSelected = get(internalSelectedData);
|
|
77
|
+
const rangeIds = [];
|
|
78
|
+
for (let i = from; i <= to; i++) {
|
|
79
|
+
const currSelectedData = tableData[i];
|
|
80
|
+
assert(currSelectedData);
|
|
81
|
+
if (isRow(currSelectedData) && !isDisabledRow(currSelectedData[rowAttr])) rangeIds.push(currSelectedData[rowAttr]);
|
|
82
|
+
}
|
|
83
|
+
if (checked) {
|
|
84
|
+
const existing = new Set(currentSelected);
|
|
85
|
+
const toAdd = rangeIds.filter((id) => !existing.has(id));
|
|
86
|
+
set(internalSelectedData, [...currentSelected, ...toAdd]);
|
|
87
|
+
} else {
|
|
88
|
+
const toRemove = new Set(rangeIds);
|
|
89
|
+
set(internalSelectedData, currentSelected.filter((id) => !toRemove.has(id)));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
71
92
|
function onCheckboxClick(event, value, index) {
|
|
72
93
|
const currentTarget = event.currentTarget;
|
|
73
94
|
if (!(currentTarget instanceof HTMLElement)) return;
|
|
@@ -80,31 +101,12 @@ function useTableSelection(options, deps) {
|
|
|
80
101
|
if (shiftKey) scheduleShiftSelect(() => {
|
|
81
102
|
let lastIndex = get(lastSelectedIndex);
|
|
82
103
|
if (lastIndex === -1) lastIndex = index;
|
|
83
|
-
const
|
|
84
|
-
const lastSelectedData = tableData[lastIndex];
|
|
104
|
+
const lastSelectedData = get(filtered)[lastIndex];
|
|
85
105
|
assert(lastSelectedData);
|
|
86
106
|
if (isRow(lastSelectedData)) {
|
|
87
107
|
const valueToApply = isSelected(lastSelectedData[rowAttr]);
|
|
88
108
|
if (lastIndex === index) onSelect(!valueToApply, value);
|
|
89
|
-
else
|
|
90
|
-
const from = Math.min(lastIndex, index);
|
|
91
|
-
const to = Math.max(lastIndex, index);
|
|
92
|
-
const currentSelected = get(internalSelectedData);
|
|
93
|
-
const rangeIds = [];
|
|
94
|
-
for (let i = from; i <= to; i++) {
|
|
95
|
-
const currSelectedData = tableData[i];
|
|
96
|
-
assert(currSelectedData);
|
|
97
|
-
if (isRow(currSelectedData) && !isDisabledRow(currSelectedData[rowAttr])) rangeIds.push(currSelectedData[rowAttr]);
|
|
98
|
-
}
|
|
99
|
-
if (valueToApply) {
|
|
100
|
-
const existing = new Set(currentSelected);
|
|
101
|
-
const toAdd = rangeIds.filter((id) => !existing.has(id));
|
|
102
|
-
set(internalSelectedData, [...currentSelected, ...toAdd]);
|
|
103
|
-
} else {
|
|
104
|
-
const toRemove = new Set(rangeIds);
|
|
105
|
-
set(internalSelectedData, currentSelected.filter((id) => !toRemove.has(id)));
|
|
106
|
-
}
|
|
107
|
-
}
|
|
109
|
+
else selectRange(Math.min(lastIndex, index), Math.max(lastIndex, index), valueToApply);
|
|
108
110
|
set(lastSelectedIndex, index);
|
|
109
111
|
set(selectedData, get(internalSelectedData));
|
|
110
112
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection.js","names":[],"sources":["../../../../src/composables/tables/data-table/selection.ts"],"sourcesContent":["import type { ComputedRef, MaybeRefOrGetter, Ref } from 'vue';\nimport { type GroupedTableRow, isRow } from '@/composables/tables/data-table/types';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { assert } from '@/utils/assert';\n\nexport interface UseTableSelectionOptions<T extends object, IdType extends keyof T> {\n /** The property on each row used as the unique row identifier. */\n rowAttr: IdType;\n /** Whether selection persists across pages. */\n multiPageSelect: boolean;\n /** Rows that cannot be selected or deselected by the user. */\n disabledRows: MaybeRefOrGetter<readonly T[] | undefined>;\n}\n\nexport interface UseTableSelectionDeps<T extends object, IdType extends keyof T> {\n selectedData: Ref<T[IdType][] | undefined>;\n filtered: ComputedRef<GroupedTableRow<T>[]>;\n}\n\nexport interface UseTableSelectionReturn<T extends object, IdType extends keyof T> {\n visibleIdentifiers: ComputedRef<T[IdType][]>;\n isAllSelected: ComputedRef<boolean>;\n indeterminate: ComputedRef<boolean>;\n isSelected: (identifier: T[IdType]) => boolean;\n isDisabledRow: (rowKey: T[IdType]) => boolean;\n isSelectable: (rowKey: T[IdType]) => boolean;\n mustSelect: (rowKey: T[IdType]) => boolean;\n onToggleAll: (checked: boolean) => void;\n onSelect: (checked: boolean, value: T[IdType], userAction?: boolean) => void;\n onCheckboxClick: (event: MouseEvent, value: T[IdType], index: number) => void;\n deselectRemovedRows: () => void;\n resetCheckboxShiftState: () => void;\n}\n\nexport function useTableSelection<T extends object, IdType extends keyof T>(\n options: UseTableSelectionOptions<T, IdType>,\n deps: UseTableSelectionDeps<T, IdType>,\n): UseTableSelectionReturn<T, IdType> {\n const { rowAttr, multiPageSelect, disabledRows } = options;\n const { selectedData, filtered } = deps;\n\n const shiftClicked: Ref<boolean> = shallowRef(false);\n const lastSelectedIndex: Ref<number> = shallowRef(-1);\n const internalSelectedData: Ref<T[IdType][]> = shallowRef([]);\n const { create: scheduleShiftSelect } = useTimeoutManager();\n\n // Sync external selection model to internal state\n watch(selectedData, val => set(internalSelectedData, val ?? []), { immediate: true });\n\n const visibleIdentifiers = computed<T[IdType][]>(() =>\n get(filtered)\n .filter(isRow)\n .map(row => row[rowAttr]),\n );\n\n const selectedSet = computed<Set<T[IdType]>>(() => new Set(get(selectedData) ?? []));\n\n const disabledRowKeySet = computed<Set<T[IdType]>>(() => {\n const currentDisabledRows = toValue(disabledRows);\n if (!currentDisabledRows || !rowAttr)\n return new Set<T[IdType]>();\n return new Set<T[IdType]>(currentDisabledRows.map((row: T) => row[rowAttr]));\n });\n\n const isAllSelected = computed<boolean>(() => {\n const selectedRows = get(selectedData);\n if (!selectedRows || selectedRows.length === 0)\n return false;\n\n const selected = get(selectedSet);\n return get(visibleIdentifiers).every(id => selected.has(id));\n });\n\n const indeterminate = computed<boolean>(() => {\n const selectedRows = get(selectedData);\n if (!selectedRows)\n return false;\n\n return selectedRows.length > 0 && !get(isAllSelected);\n });\n\n function isSelected(identifier: T[IdType]): boolean {\n return get(selectedSet).has(identifier);\n }\n\n function isDisabledRow(rowKey: T[IdType]): boolean {\n return get(disabledRowKeySet).has(rowKey);\n }\n\n function isSelectable(rowKey: T[IdType]): boolean {\n return isSelected(rowKey) || !isDisabledRow(rowKey);\n }\n\n function mustSelect(rowKey: T[IdType]): boolean {\n return isSelected(rowKey) && isDisabledRow(rowKey);\n }\n\n function resetCheckboxShiftState(): void {\n set(shiftClicked, false);\n set(lastSelectedIndex, -1);\n }\n\n function onToggleAll(checked: boolean): void {\n const selectedRows = get(selectedData);\n\n if (!isDefined(selectedRows))\n return;\n\n if (!multiPageSelect) {\n if (checked)\n set(selectedData, get(visibleIdentifiers).filter(isSelectable));\n else set(selectedData, get(visibleIdentifiers).filter(mustSelect));\n }\n else {\n if (checked) {\n set(\n selectedData,\n Array.from(new Set([...selectedRows, ...get(visibleIdentifiers).filter(isSelectable)])),\n );\n }\n else {\n const visibleSet = new Set(get(visibleIdentifiers));\n const mustSelectSet = new Set(get(visibleIdentifiers).filter(mustSelect));\n set(\n selectedData,\n selectedRows.filter(rowKey => !visibleSet.has(rowKey) || mustSelectSet.has(rowKey)),\n );\n }\n }\n }\n\n function onSelect(checked: boolean, value: T[IdType], userAction: boolean = false): void {\n if (get(shiftClicked) && userAction)\n return;\n\n const selectedRows = get(internalSelectedData);\n if (!selectedRows)\n return;\n\n const selected = isSelected(value);\n\n if (checked && !selected) {\n set(internalSelectedData, [...selectedRows, value]);\n }\n else if (!checked && selected) {\n set(\n internalSelectedData,\n selectedRows.filter(r => r !== value),\n );\n }\n\n if (userAction)\n set(selectedData, get(internalSelectedData));\n }\n\n function onCheckboxClick(event: MouseEvent, value: T[IdType], index: number): void {\n const currentTarget = event.currentTarget;\n if (!(currentTarget instanceof HTMLElement))\n return;\n\n const input = currentTarget.querySelector('input');\n const target = event.target;\n const nodeName = target instanceof HTMLElement ? target.nodeName : undefined;\n\n const shiftKey = event.shiftKey;\n set(shiftClicked, shiftKey);\n\n if (input && nodeName !== 'INPUT') {\n if (shiftKey) {\n scheduleShiftSelect(() => {\n let lastIndex = get(lastSelectedIndex);\n if (lastIndex === -1)\n lastIndex = index;\n const tableData = get(filtered);\n const lastSelectedData = tableData[lastIndex];\n assert(lastSelectedData);\n\n if (isRow(lastSelectedData)) {\n const valueToApply = isSelected(lastSelectedData[rowAttr]);\n\n if (lastIndex === index) {\n onSelect(!valueToApply, value);\n }\n else {\n const from = Math.min(lastIndex, index);\n const to = Math.max(lastIndex, index);\n\n // Batch: collect all IDs in range, then update once\n const currentSelected = get(internalSelectedData);\n const rangeIds: T[IdType][] = [];\n for (let i = from; i <= to; i++) {\n const currSelectedData = tableData[i];\n assert(currSelectedData);\n if (isRow(currSelectedData) && !isDisabledRow(currSelectedData[rowAttr]))\n rangeIds.push(currSelectedData[rowAttr]);\n }\n\n if (valueToApply) {\n const existing = new Set(currentSelected);\n const toAdd = rangeIds.filter(id => !existing.has(id));\n set(internalSelectedData, [...currentSelected, ...toAdd]);\n }\n else {\n const toRemove = new Set(rangeIds);\n set(internalSelectedData, currentSelected.filter(id => !toRemove.has(id)));\n }\n }\n\n set(lastSelectedIndex, index);\n set(selectedData, get(internalSelectedData));\n }\n }, 1);\n }\n else {\n set(lastSelectedIndex, index);\n }\n }\n }\n\n function deselectRemovedRows(): void {\n const currentSelected = get(selectedData);\n if (!currentSelected)\n return;\n\n const visibleSet = new Set(get(visibleIdentifiers));\n const remaining = currentSelected.filter(key => visibleSet.has(key));\n\n if (remaining.length !== currentSelected.length)\n set(selectedData, remaining);\n }\n\n return {\n visibleIdentifiers,\n isAllSelected,\n indeterminate,\n isSelected,\n isDisabledRow,\n isSelectable,\n mustSelect,\n onToggleAll,\n onSelect,\n onCheckboxClick,\n deselectRemovedRows,\n resetCheckboxShiftState,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"selection.js","names":[],"sources":["../../../../src/composables/tables/data-table/selection.ts"],"sourcesContent":["import type { ComputedRef, MaybeRefOrGetter, Ref } from 'vue';\nimport { type GroupedTableRow, isRow } from '@/composables/tables/data-table/types';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { assert } from '@/utils/assert';\n\nexport interface UseTableSelectionOptions<T extends object, IdType extends keyof T> {\n /** The property on each row used as the unique row identifier. */\n rowAttr: IdType;\n /** Whether selection persists across pages. */\n multiPageSelect: boolean;\n /** Rows that cannot be selected or deselected by the user. */\n disabledRows: MaybeRefOrGetter<readonly T[] | undefined>;\n}\n\nexport interface UseTableSelectionDeps<T extends object, IdType extends keyof T> {\n selectedData: Ref<T[IdType][] | undefined>;\n filtered: ComputedRef<GroupedTableRow<T>[]>;\n}\n\nexport interface UseTableSelectionReturn<T extends object, IdType extends keyof T> {\n visibleIdentifiers: ComputedRef<T[IdType][]>;\n isAllSelected: ComputedRef<boolean>;\n indeterminate: ComputedRef<boolean>;\n isSelected: (identifier: T[IdType]) => boolean;\n isDisabledRow: (rowKey: T[IdType]) => boolean;\n isSelectable: (rowKey: T[IdType]) => boolean;\n mustSelect: (rowKey: T[IdType]) => boolean;\n onToggleAll: (checked: boolean) => void;\n onSelect: (checked: boolean, value: T[IdType], userAction?: boolean) => void;\n onCheckboxClick: (event: MouseEvent, value: T[IdType], index: number) => void;\n deselectRemovedRows: () => void;\n resetCheckboxShiftState: () => void;\n}\n\nexport function useTableSelection<T extends object, IdType extends keyof T>(\n options: UseTableSelectionOptions<T, IdType>,\n deps: UseTableSelectionDeps<T, IdType>,\n): UseTableSelectionReturn<T, IdType> {\n const { rowAttr, multiPageSelect, disabledRows } = options;\n const { selectedData, filtered } = deps;\n\n const shiftClicked: Ref<boolean> = shallowRef(false);\n const lastSelectedIndex: Ref<number> = shallowRef(-1);\n const internalSelectedData: Ref<T[IdType][]> = shallowRef([]);\n const { create: scheduleShiftSelect } = useTimeoutManager();\n\n // Sync external selection model to internal state\n watch(selectedData, val => set(internalSelectedData, val ?? []), { immediate: true });\n\n const visibleIdentifiers = computed<T[IdType][]>(() =>\n get(filtered)\n .filter(isRow)\n .map(row => row[rowAttr]),\n );\n\n const selectedSet = computed<Set<T[IdType]>>(() => new Set(get(selectedData) ?? []));\n\n const disabledRowKeySet = computed<Set<T[IdType]>>(() => {\n const currentDisabledRows = toValue(disabledRows);\n if (!currentDisabledRows || !rowAttr)\n return new Set<T[IdType]>();\n return new Set<T[IdType]>(currentDisabledRows.map((row: T) => row[rowAttr]));\n });\n\n const isAllSelected = computed<boolean>(() => {\n const selectedRows = get(selectedData);\n if (!selectedRows || selectedRows.length === 0)\n return false;\n\n const selected = get(selectedSet);\n return get(visibleIdentifiers).every(id => selected.has(id));\n });\n\n const indeterminate = computed<boolean>(() => {\n const selectedRows = get(selectedData);\n if (!selectedRows)\n return false;\n\n return selectedRows.length > 0 && !get(isAllSelected);\n });\n\n function isSelected(identifier: T[IdType]): boolean {\n return get(selectedSet).has(identifier);\n }\n\n function isDisabledRow(rowKey: T[IdType]): boolean {\n return get(disabledRowKeySet).has(rowKey);\n }\n\n function isSelectable(rowKey: T[IdType]): boolean {\n return isSelected(rowKey) || !isDisabledRow(rowKey);\n }\n\n function mustSelect(rowKey: T[IdType]): boolean {\n return isSelected(rowKey) && isDisabledRow(rowKey);\n }\n\n function resetCheckboxShiftState(): void {\n set(shiftClicked, false);\n set(lastSelectedIndex, -1);\n }\n\n function onToggleAll(checked: boolean): void {\n const selectedRows = get(selectedData);\n\n if (!isDefined(selectedRows))\n return;\n\n if (!multiPageSelect) {\n if (checked)\n set(selectedData, get(visibleIdentifiers).filter(isSelectable));\n else set(selectedData, get(visibleIdentifiers).filter(mustSelect));\n }\n else {\n if (checked) {\n set(\n selectedData,\n Array.from(new Set([...selectedRows, ...get(visibleIdentifiers).filter(isSelectable)])),\n );\n }\n else {\n const visibleSet = new Set(get(visibleIdentifiers));\n const mustSelectSet = new Set(get(visibleIdentifiers).filter(mustSelect));\n set(\n selectedData,\n selectedRows.filter(rowKey => !visibleSet.has(rowKey) || mustSelectSet.has(rowKey)),\n );\n }\n }\n }\n\n function onSelect(checked: boolean, value: T[IdType], userAction: boolean = false): void {\n if (get(shiftClicked) && userAction)\n return;\n\n const selectedRows = get(internalSelectedData);\n if (!selectedRows)\n return;\n\n const selected = isSelected(value);\n\n if (checked && !selected) {\n set(internalSelectedData, [...selectedRows, value]);\n }\n else if (!checked && selected) {\n set(\n internalSelectedData,\n selectedRows.filter(r => r !== value),\n );\n }\n\n if (userAction)\n set(selectedData, get(internalSelectedData));\n }\n\n /**\n * Checks or unchecks every selectable row from `from` to `to`, updating the selection once.\n */\n function selectRange(from: number, to: number, checked: boolean): void {\n const tableData = get(filtered);\n const currentSelected = get(internalSelectedData);\n const rangeIds: T[IdType][] = [];\n for (let i = from; i <= to; i++) {\n const currSelectedData = tableData[i];\n assert(currSelectedData);\n if (isRow(currSelectedData) && !isDisabledRow(currSelectedData[rowAttr]))\n rangeIds.push(currSelectedData[rowAttr]);\n }\n\n if (checked) {\n const existing = new Set(currentSelected);\n const toAdd = rangeIds.filter(id => !existing.has(id));\n set(internalSelectedData, [...currentSelected, ...toAdd]);\n }\n else {\n const toRemove = new Set(rangeIds);\n set(internalSelectedData, currentSelected.filter(id => !toRemove.has(id)));\n }\n }\n\n function onCheckboxClick(event: MouseEvent, value: T[IdType], index: number): void {\n const currentTarget = event.currentTarget;\n if (!(currentTarget instanceof HTMLElement))\n return;\n\n const input = currentTarget.querySelector('input');\n const target = event.target;\n const nodeName = target instanceof HTMLElement ? target.nodeName : undefined;\n\n const shiftKey = event.shiftKey;\n set(shiftClicked, shiftKey);\n\n if (input && nodeName !== 'INPUT') {\n if (shiftKey) {\n scheduleShiftSelect(() => {\n let lastIndex = get(lastSelectedIndex);\n if (lastIndex === -1)\n lastIndex = index;\n const lastSelectedData = get(filtered)[lastIndex];\n assert(lastSelectedData);\n\n if (isRow(lastSelectedData)) {\n const valueToApply = isSelected(lastSelectedData[rowAttr]);\n\n if (lastIndex === index)\n onSelect(!valueToApply, value);\n else\n selectRange(Math.min(lastIndex, index), Math.max(lastIndex, index), valueToApply);\n\n set(lastSelectedIndex, index);\n set(selectedData, get(internalSelectedData));\n }\n }, 1);\n }\n else {\n set(lastSelectedIndex, index);\n }\n }\n }\n\n function deselectRemovedRows(): void {\n const currentSelected = get(selectedData);\n if (!currentSelected)\n return;\n\n const visibleSet = new Set(get(visibleIdentifiers));\n const remaining = currentSelected.filter(key => visibleSet.has(key));\n\n if (remaining.length !== currentSelected.length)\n set(selectedData, remaining);\n }\n\n return {\n visibleIdentifiers,\n isAllSelected,\n indeterminate,\n isSelected,\n isDisabledRow,\n isSelectable,\n mustSelect,\n onToggleAll,\n onSelect,\n onCheckboxClick,\n deselectRemovedRows,\n resetCheckboxShiftState,\n };\n}\n"],"mappings":"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"}
|