@inglorious/ui 9.10.0 → 9.11.0
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 +2 -1
- package/src/controls/checkbox/template.js +3 -1
- package/src/controls/combobox/handlers.js +2 -1
- package/src/controls/combobox/template.js +3 -1
- package/src/controls/radio-group/template.js +3 -1
- package/src/controls/rating/template.js +4 -1
- package/src/controls/select/template.js +6 -12
- package/src/controls/switch/template.js +3 -1
- package/src/data-display/badge/style.css +1 -0
- package/src/data-display/data-grid/handlers.js +2 -0
- package/src/data-display/data-grid/helpers.js +9 -2
- package/src/shared/live-boolean.js +17 -0
- package/types/data-display/data-grid.d.ts +7 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inglorious/ui",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.11.0",
|
|
4
4
|
"description": "A design system for Inglorious Web with render-function components and customizable themes",
|
|
5
5
|
"author": "Matteo Antony Mistretta <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -354,6 +354,7 @@
|
|
|
354
354
|
"@inglorious/vite-plugin-jsx": "2.0.6",
|
|
355
355
|
"@inglorious/vite-plugin-vue": "1.0.7",
|
|
356
356
|
"@inglorious/web": "6.14.0",
|
|
357
|
+
"@lit-labs/ssr": "^4.1.0",
|
|
357
358
|
"@storybook/addon-docs": "^10.6.5",
|
|
358
359
|
"@storybook/web-components-vite": "^10.6.5",
|
|
359
360
|
"happy-dom": "^20.14.0",
|
|
@@ -9,6 +9,7 @@ import { ref } from "@inglorious/web/directives/ref"
|
|
|
9
9
|
import { when } from "@inglorious/web/directives/when"
|
|
10
10
|
|
|
11
11
|
import { applyElementProps } from "../../shared/apply-element-props.js"
|
|
12
|
+
import { liveBoolean } from "../../shared/live-boolean.js"
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Renders a labeled checkbox for boolean input.
|
|
@@ -51,7 +52,8 @@ export function render(props) {
|
|
|
51
52
|
class="iw-checkbox-input"
|
|
52
53
|
type="checkbox"
|
|
53
54
|
name=${name}
|
|
54
|
-
|
|
55
|
+
?checked=${isChecked}
|
|
56
|
+
${liveBoolean("checked", isChecked)}
|
|
55
57
|
?disabled=${isDisabled}
|
|
56
58
|
?required=${isRequired}
|
|
57
59
|
@change=${(event) => onChange?.(event.target.checked)}
|
|
@@ -46,6 +46,7 @@ export function open(entity) {
|
|
|
46
46
|
/** @param {SelectEntity} entity */
|
|
47
47
|
export function close(entity) {
|
|
48
48
|
entity.isOpen = false
|
|
49
|
+
entity.searchTerm = ""
|
|
49
50
|
entity.focusedIndex = NONE
|
|
50
51
|
}
|
|
51
52
|
|
|
@@ -67,7 +68,7 @@ export function optionSelect(entity, option, api) {
|
|
|
67
68
|
if (normalizedOption.isDisabled) return
|
|
68
69
|
const optionValue = getOptionValue(normalizedOption)
|
|
69
70
|
|
|
70
|
-
if (normalizedOption.isCreated) {
|
|
71
|
+
if (normalizedOption.isCreated || entity.searchTerm) {
|
|
71
72
|
entity.searchTerm = ""
|
|
72
73
|
entity.focusedIndex = NONE
|
|
73
74
|
}
|
|
@@ -12,6 +12,7 @@ import { when } from "@inglorious/web/directives/when"
|
|
|
12
12
|
|
|
13
13
|
import { Chip } from "../../data-display/chip/index.js"
|
|
14
14
|
import { fallbackLabel } from "../../shared/fallback-label.js"
|
|
15
|
+
import { liveBoolean } from "../../shared/live-boolean.js"
|
|
15
16
|
import { syncPopover } from "../../shared/top-layer.js"
|
|
16
17
|
import {
|
|
17
18
|
formatOption,
|
|
@@ -384,7 +385,8 @@ export const Combobox = {
|
|
|
384
385
|
() =>
|
|
385
386
|
html`<input
|
|
386
387
|
type="checkbox"
|
|
387
|
-
|
|
388
|
+
?checked=${isSelected}
|
|
389
|
+
${liveBoolean("checked", isSelected)}
|
|
388
390
|
?disabled=${!!normalized.isDisabled}
|
|
389
391
|
/>`,
|
|
390
392
|
)}
|
|
@@ -9,6 +9,7 @@ import { ref } from "@inglorious/web/directives/ref"
|
|
|
9
9
|
import { when } from "@inglorious/web/directives/when"
|
|
10
10
|
|
|
11
11
|
import { applyElementProps } from "../../shared/apply-element-props.js"
|
|
12
|
+
import { liveBoolean } from "../../shared/live-boolean.js"
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Renders a group of radio options for single selection.
|
|
@@ -72,7 +73,8 @@ export function render(props) {
|
|
|
72
73
|
type="radio"
|
|
73
74
|
name=${groupName || nothing}
|
|
74
75
|
value=${optionValue}
|
|
75
|
-
|
|
76
|
+
?checked=${value === optionValue}
|
|
77
|
+
${liveBoolean("checked", value === optionValue)}
|
|
76
78
|
?disabled=${isDisabled || optionDisabled}
|
|
77
79
|
@change=${(event) => onChange?.(event.target.value)}
|
|
78
80
|
${ref((element) => applyElementProps(element, optionRest))}
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
import { html, nothing } from "@inglorious/web"
|
|
7
7
|
import { classMap } from "@inglorious/web/directives/class-map"
|
|
8
8
|
|
|
9
|
+
import { liveBoolean } from "../../shared/live-boolean.js"
|
|
10
|
+
|
|
9
11
|
const DEFAULT_VALUE = 0
|
|
10
12
|
const DEFAULT_MAX = 5
|
|
11
13
|
const INDEX_TO_RATING = 1
|
|
@@ -62,7 +64,8 @@ export function render(props) {
|
|
|
62
64
|
name=${groupName || nothing}
|
|
63
65
|
value=${ratingValue}
|
|
64
66
|
aria-label=${`${ratingValue} of ${max}`}
|
|
65
|
-
|
|
67
|
+
?checked=${ratingValue === value}
|
|
68
|
+
${liveBoolean("checked", ratingValue === value)}
|
|
66
69
|
@change=${() => onChange?.(ratingValue)}
|
|
67
70
|
/>
|
|
68
71
|
<span aria-hidden="true">${isActive ? symbol : emptySymbol}</span>
|
|
@@ -10,6 +10,7 @@ import { when } from "@inglorious/web/directives/when"
|
|
|
10
10
|
|
|
11
11
|
import { Icon } from "../../data-display/icon/index.js"
|
|
12
12
|
import { fallbackLabel } from "../../shared/fallback-label.js"
|
|
13
|
+
import { liveBoolean } from "../../shared/live-boolean.js"
|
|
13
14
|
import { formatOption, getOptionValue, isOptionSelected } from "./helpers.js"
|
|
14
15
|
|
|
15
16
|
/**
|
|
@@ -111,10 +112,6 @@ export const Select = {
|
|
|
111
112
|
"iw-select-control-error": !!error,
|
|
112
113
|
}
|
|
113
114
|
|
|
114
|
-
const selectedOption = options.find(
|
|
115
|
-
(option) => getOptionValue(option) === value,
|
|
116
|
-
)
|
|
117
|
-
|
|
118
115
|
return html`<div class="iw-select-frame" @click=${openFromArrowStrip}>
|
|
119
116
|
${when(icon, () => Icon.render({ children: icon, size }))}
|
|
120
117
|
|
|
@@ -137,15 +134,11 @@ export const Select = {
|
|
|
137
134
|
(option) => getOptionValue(option),
|
|
138
135
|
(option) => {
|
|
139
136
|
const {
|
|
140
|
-
value,
|
|
137
|
+
value: optionValue,
|
|
141
138
|
label,
|
|
142
139
|
isDisabled: isOptionDisabled,
|
|
143
140
|
} = formatOption(option)
|
|
144
|
-
const isSelected = isOptionSelected(
|
|
145
|
-
option,
|
|
146
|
-
selectedOption?.value,
|
|
147
|
-
isMulti,
|
|
148
|
-
)
|
|
141
|
+
const isSelected = isOptionSelected(option, value, isMulti)
|
|
149
142
|
|
|
150
143
|
const optionClasses = {
|
|
151
144
|
"iw-select-option": true,
|
|
@@ -153,8 +146,9 @@ export const Select = {
|
|
|
153
146
|
}
|
|
154
147
|
|
|
155
148
|
return html`<option
|
|
156
|
-
value=${
|
|
157
|
-
|
|
149
|
+
value=${optionValue}
|
|
150
|
+
?selected=${isSelected}
|
|
151
|
+
${liveBoolean("selected", isSelected)}
|
|
158
152
|
?disabled=${isOptionDisabled}
|
|
159
153
|
class=${classMap(optionClasses)}
|
|
160
154
|
>
|
|
@@ -9,6 +9,7 @@ import { ref } from "@inglorious/web/directives/ref"
|
|
|
9
9
|
import { when } from "@inglorious/web/directives/when"
|
|
10
10
|
|
|
11
11
|
import { applyElementProps } from "../../shared/apply-element-props.js"
|
|
12
|
+
import { liveBoolean } from "../../shared/live-boolean.js"
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Renders a toggle switch backed by a checkbox input, which `role="switch"`
|
|
@@ -49,7 +50,8 @@ export function render(props) {
|
|
|
49
50
|
type="checkbox"
|
|
50
51
|
role="switch"
|
|
51
52
|
name=${name}
|
|
52
|
-
|
|
53
|
+
?checked=${isChecked}
|
|
54
|
+
${liveBoolean("checked", isChecked)}
|
|
53
55
|
?disabled=${isDisabled}
|
|
54
56
|
@change=${(event) => onChange?.(event.target.checked)}
|
|
55
57
|
${ref((element) => applyElementProps(element, rest))}
|
|
@@ -60,11 +60,15 @@ export function getEditedRows(entity) {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
|
-
* Gets the processed rows (filtered, searched, sorted, paginated).
|
|
63
|
+
* Gets the processed rows (filtered, searched, sorted, paginated). A grid with
|
|
64
|
+
* `totalRows` holds the server's page already processed, so it gets the rows
|
|
65
|
+
* as they are.
|
|
64
66
|
* @param {TableEntity} entity
|
|
65
67
|
* @returns {any[]}
|
|
66
68
|
*/
|
|
67
69
|
export function getRows(entity) {
|
|
70
|
+
if (entity.totalRows != null) return entity.rows
|
|
71
|
+
|
|
68
72
|
let rows = entity.rows
|
|
69
73
|
rows = applyFilters(entity, rows)
|
|
70
74
|
rows = applySearch(entity, rows)
|
|
@@ -75,11 +79,14 @@ export function getRows(entity) {
|
|
|
75
79
|
}
|
|
76
80
|
|
|
77
81
|
/**
|
|
78
|
-
* Gets the total number of rows after filtering and searching
|
|
82
|
+
* Gets the total number of rows after filtering and searching, or the
|
|
83
|
+
* server's `totalRows` when the grid has it.
|
|
79
84
|
* @param {TableEntity} entity
|
|
80
85
|
* @returns {number}
|
|
81
86
|
*/
|
|
82
87
|
export function getTotalRows(entity) {
|
|
88
|
+
if (entity.totalRows != null) return entity.totalRows
|
|
89
|
+
|
|
83
90
|
let rows = entity.rows
|
|
84
91
|
rows = applyFilters(entity, rows)
|
|
85
92
|
rows = applySearch(entity, rows)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ref } from "@inglorious/web/directives/ref"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Keeps an element's `checked` or `selected` property in step with the state.
|
|
5
|
+
*
|
|
6
|
+
* A `.checked=${false}` binding can't be used instead: server rendering
|
|
7
|
+
* reflects it as `checked="false"`, which HTML reads as checked. Templates pair
|
|
8
|
+
* this with the boolean attribute (`?checked=${value}`), which renders right on
|
|
9
|
+
* the server but stops counting once the user has touched the control.
|
|
10
|
+
* @param {"checked" | "selected"} name
|
|
11
|
+
* @param {boolean} value
|
|
12
|
+
*/
|
|
13
|
+
export function liveBoolean(name, value) {
|
|
14
|
+
return ref((element) => {
|
|
15
|
+
if (element) element[name] = value
|
|
16
|
+
})
|
|
17
|
+
}
|
|
@@ -75,6 +75,13 @@ export interface DataGridProps<T extends Row = Row> {
|
|
|
75
75
|
selectionAnchor?: string | number | null
|
|
76
76
|
pagination?: { page: number; pageSize: number; pageSizes: number[] } | null
|
|
77
77
|
rowId?: string
|
|
78
|
+
/**
|
|
79
|
+
* How many rows the server has for the current filters and search. When it
|
|
80
|
+
* is set, `rows` is the page the server already filtered, sorted and sliced,
|
|
81
|
+
* so the grid shows them as they are and pages by this total. Set it to `0`
|
|
82
|
+
* before the first load to start the grid server-side.
|
|
83
|
+
*/
|
|
84
|
+
totalRows?: number | null
|
|
78
85
|
isMultiSelect: boolean
|
|
79
86
|
/**
|
|
80
87
|
* The user's unsaved edits, by row key and column id, shown over the rows
|