@inglorious/ui 8.4.0 → 8.4.2
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 +10 -10
- package/src/controls/fab/fab.stories.js +1 -1
- package/src/controls/select/template.js +34 -34
- package/src/data-display/carousel/carousel.stories.js +9 -8
- package/src/data-display/data-grid/data-grid.stories.js +10 -10
- package/src/data-display/data-grid/filters/input.js +2 -2
- package/src/data-display/data-grid/filters/range.js +2 -2
- package/src/data-display/data-grid/filters/select.js +2 -2
- package/src/data-display/data-grid/template.js +1 -1
- package/src/data-display/icon/icon-utf8.stories.js +1 -1
- package/src/data-display/list/template.js +3 -3
- package/src/data-display/virtual-list/template.js +21 -21
- package/src/examples/dashboard/app-drawer.js +6 -6
- package/src/examples/dashboard/app-header.js +7 -7
- package/src/examples/dashboard/before-after-data.js +17 -14
- package/src/examples/dashboard/primitive-content.js +32 -30
- package/src/examples/dashboard/social-card.js +5 -5
- package/src/examples/dashboard/stat-card.js +4 -4
- package/src/examples/dashboard/theme-utils.js +5 -5
- package/src/examples/dashboard/traffic-card.js +9 -9
- package/src/examples/dashboard/traffic-sales-card.js +11 -11
- package/src/feedback/progress/template.js +4 -4
- package/src/navigation/drawer/template.js +4 -4
- package/src/shared/apply-element-props.js +27 -27
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inglorious/ui",
|
|
3
|
-
"version": "8.4.
|
|
3
|
+
"version": "8.4.2",
|
|
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",
|
|
@@ -306,21 +306,21 @@
|
|
|
306
306
|
"**/*.css"
|
|
307
307
|
],
|
|
308
308
|
"peerDependencies": {
|
|
309
|
-
"@inglorious/store": "
|
|
310
|
-
"@inglorious/utils": "5.
|
|
311
|
-
"@inglorious/web": "6.8.
|
|
309
|
+
"@inglorious/store": "12.0.0",
|
|
310
|
+
"@inglorious/utils": "5.1.0",
|
|
311
|
+
"@inglorious/web": "6.8.1"
|
|
312
312
|
},
|
|
313
313
|
"devDependencies": {
|
|
314
314
|
"@iconify-icons/fa7-brands": "^2.0.0",
|
|
315
315
|
"@iconify-icons/fa7-regular": "^2.0.0",
|
|
316
316
|
"@iconify-icons/fa7-solid": "^2.0.0",
|
|
317
317
|
"@iconify-icons/material-symbols": "^2.0.6",
|
|
318
|
-
"@inglorious/charts": "11.1.
|
|
319
|
-
"@inglorious/eslint-config": "1.
|
|
320
|
-
"@inglorious/store": "
|
|
321
|
-
"@inglorious/vite-plugin-jsx": "2.0.
|
|
322
|
-
"@inglorious/vite-plugin-vue": "1.0.
|
|
323
|
-
"@inglorious/web": "6.8.
|
|
318
|
+
"@inglorious/charts": "11.1.6",
|
|
319
|
+
"@inglorious/eslint-config": "1.2.0",
|
|
320
|
+
"@inglorious/store": "12.0.0",
|
|
321
|
+
"@inglorious/vite-plugin-jsx": "2.0.5",
|
|
322
|
+
"@inglorious/vite-plugin-vue": "1.0.6",
|
|
323
|
+
"@inglorious/web": "6.8.1",
|
|
324
324
|
"@storybook/addon-docs": "^10.6.0",
|
|
325
325
|
"@storybook/web-components-vite": "^10.6.0",
|
|
326
326
|
"happy-dom": "^20.14.0",
|
|
@@ -12,40 +12,6 @@ import { Icon } from "../../data-display/icon/index.js"
|
|
|
12
12
|
import { fallbackLabel } from "../../shared/fallback-label.js"
|
|
13
13
|
import { formatOption, getOptionValue, isOptionSelected } from "./helpers.js"
|
|
14
14
|
|
|
15
|
-
/**
|
|
16
|
-
* Opens the native dropdown when the arrow strip is pressed.
|
|
17
|
-
*
|
|
18
|
-
* The arrow is a sibling of the select, not an overlay on it, so a press on it
|
|
19
|
-
* has no control underneath to hit. A native popup only opens from a trusted
|
|
20
|
-
* gesture on the select itself, and the strip is outside it.
|
|
21
|
-
*
|
|
22
|
-
* `showPicker()` is the API for that. It needs transient user activation, which
|
|
23
|
-
* a real click has and a dispatched event does not, and it throws rather than
|
|
24
|
-
* silently doing nothing, so the fallback covers the browsers without it.
|
|
25
|
-
*
|
|
26
|
-
* Deliberately on `click`, not `pointerdown`: focusing from pointerdown gets
|
|
27
|
-
* the focus moved away again by the browser's own mousedown handling, which
|
|
28
|
-
* showed up as a focus immediately followed by a blur.
|
|
29
|
-
*
|
|
30
|
-
* @param {MouseEvent} event
|
|
31
|
-
*/
|
|
32
|
-
function openFromArrowStrip(event) {
|
|
33
|
-
const frame = event.currentTarget
|
|
34
|
-
const select = frame?.querySelector("select")
|
|
35
|
-
if (!select || select.disabled || event.target === select) return
|
|
36
|
-
|
|
37
|
-
event.preventDefault()
|
|
38
|
-
if (typeof select.showPicker === "function") {
|
|
39
|
-
try {
|
|
40
|
-
select.showPicker()
|
|
41
|
-
return
|
|
42
|
-
} catch {
|
|
43
|
-
// No user activation, or the popup is already showing.
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
select.focus()
|
|
47
|
-
}
|
|
48
|
-
|
|
49
15
|
/**
|
|
50
16
|
* Renders a styled native select control with optional single or multi-select modes.
|
|
51
17
|
* Options can be primitives or objects and are rendered with consistent theming.
|
|
@@ -208,3 +174,37 @@ export const Select = {
|
|
|
208
174
|
</div>`
|
|
209
175
|
},
|
|
210
176
|
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Opens the native dropdown when the arrow strip is pressed.
|
|
180
|
+
*
|
|
181
|
+
* The arrow is a sibling of the select, not an overlay on it, so a press on it
|
|
182
|
+
* has no control underneath to hit. A native popup only opens from a trusted
|
|
183
|
+
* gesture on the select itself, and the strip is outside it.
|
|
184
|
+
*
|
|
185
|
+
* `showPicker()` is the API for that. It needs transient user activation, which
|
|
186
|
+
* a real click has and a dispatched event does not, and it throws rather than
|
|
187
|
+
* silently doing nothing, so the fallback covers the browsers without it.
|
|
188
|
+
*
|
|
189
|
+
* Deliberately on `click`, not `pointerdown`: focusing from pointerdown gets
|
|
190
|
+
* the focus moved away again by the browser's own mousedown handling, which
|
|
191
|
+
* showed up as a focus immediately followed by a blur.
|
|
192
|
+
*
|
|
193
|
+
* @param {MouseEvent} event
|
|
194
|
+
*/
|
|
195
|
+
function openFromArrowStrip(event) {
|
|
196
|
+
const frame = event.currentTarget
|
|
197
|
+
const select = frame?.querySelector("select")
|
|
198
|
+
if (!select || select.disabled || event.target === select) return
|
|
199
|
+
|
|
200
|
+
event.preventDefault()
|
|
201
|
+
if (typeof select.showPicker === "function") {
|
|
202
|
+
try {
|
|
203
|
+
select.showPicker()
|
|
204
|
+
return
|
|
205
|
+
} catch {
|
|
206
|
+
// No user activation, or the popup is already showing.
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
select.focus()
|
|
210
|
+
}
|
|
@@ -8,14 +8,6 @@ import { Carousel } from "./index.js"
|
|
|
8
8
|
|
|
9
9
|
const COLORS = ["#22d3ee", "#4f46e5", "#f59e0b", "#10b981", "#ef4444"]
|
|
10
10
|
|
|
11
|
-
const slide = (index) =>
|
|
12
|
-
html`<div
|
|
13
|
-
style="display:grid;place-items:center;height:14rem;border-radius:0.5rem;
|
|
14
|
-
background:${COLORS[index]};color:#fff;font:700 2rem sans-serif;"
|
|
15
|
-
>
|
|
16
|
-
${index + 1}
|
|
17
|
-
</div>`
|
|
18
|
-
|
|
19
11
|
const items = COLORS.map((color, index) => slide(index))
|
|
20
12
|
|
|
21
13
|
export default {
|
|
@@ -164,3 +156,12 @@ ManyPerView.args = {
|
|
|
164
156
|
ManyPerView.decorators = [
|
|
165
157
|
(story) => html`<div style="--iw-carousel-item-size: 14rem">${story()}</div>`,
|
|
166
158
|
]
|
|
159
|
+
|
|
160
|
+
function slide(index) {
|
|
161
|
+
return html`<div
|
|
162
|
+
style="display:grid;place-items:center;height:14rem;border-radius:0.5rem;
|
|
163
|
+
background:${COLORS[index]};color:#fff;font:700 2rem sans-serif;"
|
|
164
|
+
>
|
|
165
|
+
${index + 1}
|
|
166
|
+
</div>`
|
|
167
|
+
}
|
|
@@ -44,16 +44,6 @@ const baseColumns = [
|
|
|
44
44
|
},
|
|
45
45
|
]
|
|
46
46
|
|
|
47
|
-
function createRows(count) {
|
|
48
|
-
return Array.from({ length: count }, (_, index) => ({
|
|
49
|
-
id: index + 1,
|
|
50
|
-
name: `User ${index + 1}`,
|
|
51
|
-
age: 20 + (index % 35),
|
|
52
|
-
active: index % 3 !== 0,
|
|
53
|
-
role: index % 4 === 0 ? "Admin" : "User",
|
|
54
|
-
}))
|
|
55
|
-
}
|
|
56
|
-
|
|
57
47
|
export default {
|
|
58
48
|
title: "Data Display/DataGrid",
|
|
59
49
|
tags: ["autodocs"],
|
|
@@ -156,3 +146,13 @@ export const Virtualized = {
|
|
|
156
146
|
},
|
|
157
147
|
},
|
|
158
148
|
}
|
|
149
|
+
|
|
150
|
+
function createRows(count) {
|
|
151
|
+
return Array.from({ length: count }, (_, index) => ({
|
|
152
|
+
id: index + 1,
|
|
153
|
+
name: `User ${index + 1}`,
|
|
154
|
+
age: 20 + (index % 35),
|
|
155
|
+
active: index % 3 !== 0,
|
|
156
|
+
role: index % 4 === 0 ? "Admin" : "User",
|
|
157
|
+
}))
|
|
158
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { html } from "@inglorious/web"
|
|
2
2
|
|
|
3
|
-
import { Input } from "../../../controls/input"
|
|
4
|
-
import { format } from "./helpers"
|
|
3
|
+
import { Input } from "../../../controls/input/index.js"
|
|
4
|
+
import { format } from "./helpers.js"
|
|
5
5
|
|
|
6
6
|
const RANGE_TYPE = {
|
|
7
7
|
range: "number",
|
|
@@ -14,7 +14,7 @@ import { Input } from "../../controls/input/index.js"
|
|
|
14
14
|
import { Select } from "../../controls/select/index.js"
|
|
15
15
|
import { Pagination } from "../../navigation/pagination/index.js"
|
|
16
16
|
import { VirtualList } from "../virtual-list/index.js"
|
|
17
|
-
import { Filters } from "./filters"
|
|
17
|
+
import { Filters } from "./filters/index.js"
|
|
18
18
|
import {
|
|
19
19
|
getPaginationInfo,
|
|
20
20
|
getRowKeyValue,
|
|
@@ -2,7 +2,7 @@ import { VirtualList } from "@inglorious/ui/virtual-list"
|
|
|
2
2
|
import { html } from "@inglorious/web"
|
|
3
3
|
import { repeat } from "@inglorious/web/directives/repeat"
|
|
4
4
|
|
|
5
|
-
import { Button } from "../../controls/button"
|
|
5
|
+
import { Button } from "../../controls/button/index.js"
|
|
6
6
|
import {
|
|
7
7
|
createEntityRender,
|
|
8
8
|
notifyActionArgType,
|
|
@@ -25,9 +25,9 @@ import { ref } from "@inglorious/web/directives/ref"
|
|
|
25
25
|
import { repeat } from "@inglorious/web/directives/repeat"
|
|
26
26
|
import { when } from "@inglorious/web/directives/when"
|
|
27
27
|
|
|
28
|
-
import { IconButton } from "../../controls/icon-button"
|
|
29
|
-
import { Icon } from "../../data-display/icon"
|
|
30
|
-
import { Flex } from "../../layout/flex"
|
|
28
|
+
import { IconButton } from "../../controls/icon-button/index.js"
|
|
29
|
+
import { Icon } from "../../data-display/icon/index.js"
|
|
30
|
+
import { Flex } from "../../layout/flex/index.js"
|
|
31
31
|
import { applyElementProps } from "../../shared/apply-element-props.js"
|
|
32
32
|
|
|
33
33
|
const PRETTY_INDEX = 1
|
|
@@ -15,27 +15,6 @@ const PRETTY_INDEX = 1
|
|
|
15
15
|
// measuring is an update, so measuring on each render would loop forever.
|
|
16
16
|
const measured = new WeakSet()
|
|
17
17
|
|
|
18
|
-
/**
|
|
19
|
-
* Notifies `mount` once per list element, after a frame and once it is in the
|
|
20
|
-
* document: before that it has no layout to measure.
|
|
21
|
-
* @param {HTMLElement} el
|
|
22
|
-
* @param {VirtualListEntity} entity
|
|
23
|
-
* @param {Api} api
|
|
24
|
-
*/
|
|
25
|
-
function measureOnce(el, entity, api) {
|
|
26
|
-
if (measured.has(el)) return
|
|
27
|
-
measured.add(el)
|
|
28
|
-
|
|
29
|
-
const measure = () => {
|
|
30
|
-
if (!el.isConnected) {
|
|
31
|
-
requestAnimationFrame(measure)
|
|
32
|
-
return
|
|
33
|
-
}
|
|
34
|
-
api.notify(`#${entity.id}:mount`, el)
|
|
35
|
-
}
|
|
36
|
-
requestAnimationFrame(measure)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
18
|
/**
|
|
40
19
|
* Renders a virtualized list that only mounts visible items for performance.
|
|
41
20
|
* Uses item height estimates to compute scroll ranges and notifies on mount/scroll.
|
|
@@ -125,3 +104,24 @@ export function renderItem(entity, { item, index }, api) {
|
|
|
125
104
|
${index + PRETTY_INDEX}. ${JSON.stringify(item)}
|
|
126
105
|
</div>`
|
|
127
106
|
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Notifies `mount` once per list element, after a frame and once it is in the
|
|
110
|
+
* document: before that it has no layout to measure.
|
|
111
|
+
* @param {HTMLElement} el
|
|
112
|
+
* @param {VirtualListEntity} entity
|
|
113
|
+
* @param {Api} api
|
|
114
|
+
*/
|
|
115
|
+
function measureOnce(el, entity, api) {
|
|
116
|
+
if (measured.has(el)) return
|
|
117
|
+
measured.add(el)
|
|
118
|
+
|
|
119
|
+
const measure = () => {
|
|
120
|
+
if (!el.isConnected) {
|
|
121
|
+
requestAnimationFrame(measure)
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
api.notify(`#${entity.id}:mount`, el)
|
|
125
|
+
}
|
|
126
|
+
requestAnimationFrame(measure)
|
|
127
|
+
}
|
|
@@ -7,12 +7,12 @@ import notificationsOutline from "@iconify-icons/material-symbols/notifications-
|
|
|
7
7
|
import speedOutline from "@iconify-icons/material-symbols/speed-outline"
|
|
8
8
|
import { html } from "@inglorious/web"
|
|
9
9
|
|
|
10
|
-
import { Avatar } from "../../data-display/avatar"
|
|
11
|
-
import { Badge } from "../../data-display/badge"
|
|
12
|
-
import { Icon } from "../../data-display/icon"
|
|
13
|
-
import { List } from "../../data-display/list"
|
|
14
|
-
import { Flex } from "../../layout/flex"
|
|
15
|
-
import { Drawer } from "../../navigation/drawer"
|
|
10
|
+
import { Avatar } from "../../data-display/avatar/index.js"
|
|
11
|
+
import { Badge } from "../../data-display/badge/index.js"
|
|
12
|
+
import { Icon } from "../../data-display/icon/index.js"
|
|
13
|
+
import { List } from "../../data-display/list/index.js"
|
|
14
|
+
import { Flex } from "../../layout/flex/index.js"
|
|
15
|
+
import { Drawer } from "../../navigation/drawer/index.js"
|
|
16
16
|
|
|
17
17
|
export const AppDrawer = {
|
|
18
18
|
create(entity) {
|
|
@@ -10,13 +10,13 @@ import menuOutline from "@iconify-icons/material-symbols/menu-outline"
|
|
|
10
10
|
import notificationsOutline from "@iconify-icons/material-symbols/notifications-outline"
|
|
11
11
|
import { html } from "@inglorious/web"
|
|
12
12
|
|
|
13
|
-
import { Button } from "../../controls/button"
|
|
14
|
-
import { Avatar } from "../../data-display/avatar"
|
|
15
|
-
import { Divider } from "../../data-display/divider"
|
|
16
|
-
import { Icon } from "../../data-display/icon"
|
|
17
|
-
import { Flex } from "../../layout/flex"
|
|
18
|
-
import { Breadcrumbs } from "../../navigation/breadcrumbs"
|
|
19
|
-
import { AppBar } from "../../surfaces/app-bar"
|
|
13
|
+
import { Button } from "../../controls/button/index.js"
|
|
14
|
+
import { Avatar } from "../../data-display/avatar/index.js"
|
|
15
|
+
import { Divider } from "../../data-display/divider/index.js"
|
|
16
|
+
import { Icon } from "../../data-display/icon/index.js"
|
|
17
|
+
import { Flex } from "../../layout/flex/index.js"
|
|
18
|
+
import { Breadcrumbs } from "../../navigation/breadcrumbs/index.js"
|
|
19
|
+
import { AppBar } from "../../surfaces/app-bar/index.js"
|
|
20
20
|
|
|
21
21
|
export const AppHeader = {
|
|
22
22
|
render(entity, api) {
|
|
@@ -1,10 +1,22 @@
|
|
|
1
|
+
export const beforeAfterImages = {
|
|
2
|
+
before: {
|
|
3
|
+
src: svg("BEFORE", "#9ca3af", "#374151"),
|
|
4
|
+
alt: "Before — grayscale",
|
|
5
|
+
},
|
|
6
|
+
after: {
|
|
7
|
+
src: svg("AFTER", "#22d3ee", "#4f46e5"),
|
|
8
|
+
alt: "After — color graded",
|
|
9
|
+
},
|
|
10
|
+
}
|
|
11
|
+
|
|
1
12
|
// Self-contained demo images for the Before/After control, so the dashboard
|
|
2
13
|
// renders the comparison without any network requests.
|
|
3
14
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
15
|
+
function svg(label, from, to) {
|
|
16
|
+
return (
|
|
17
|
+
"data:image/svg+xml," +
|
|
18
|
+
encodeURIComponent(
|
|
19
|
+
`<svg xmlns="http://www.w3.org/2000/svg" width="960" height="540" viewBox="0 0 960 540">
|
|
8
20
|
<defs>
|
|
9
21
|
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1">
|
|
10
22
|
<stop offset="0" stop-color="${from}"/>
|
|
@@ -15,15 +27,6 @@ const svg = (label, from, to) =>
|
|
|
15
27
|
<text x="48" y="496" font-family="sans-serif" font-size="72" font-weight="700"
|
|
16
28
|
fill="rgba(255,255,255,0.92)">${label}</text>
|
|
17
29
|
</svg>`,
|
|
30
|
+
)
|
|
18
31
|
)
|
|
19
|
-
|
|
20
|
-
export const beforeAfterImages = {
|
|
21
|
-
before: {
|
|
22
|
-
src: svg("BEFORE", "#9ca3af", "#374151"),
|
|
23
|
-
alt: "Before — grayscale",
|
|
24
|
-
},
|
|
25
|
-
after: {
|
|
26
|
-
src: svg("AFTER", "#22d3ee", "#4f46e5"),
|
|
27
|
-
alt: "After — color graded",
|
|
28
|
-
},
|
|
29
32
|
}
|
|
@@ -114,38 +114,8 @@ const categoryMeta = {
|
|
|
114
114
|
},
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
const previewRow = (children) =>
|
|
118
|
-
html`<div class="iw-primitive-preview-row">${children}</div>`
|
|
119
|
-
|
|
120
|
-
const previewColumn = (children) =>
|
|
121
|
-
html`<div class="iw-primitive-preview-column">${children}</div>`
|
|
122
|
-
|
|
123
117
|
const livePreviews = new Map()
|
|
124
118
|
|
|
125
|
-
/**
|
|
126
|
-
* Entity-driven primitives render their controls from state, so a preview
|
|
127
|
-
* without a store freezes: a carousel arrow would recompute from the same page
|
|
128
|
-
* forever, and a dragged divider would never move. Give each one its own store,
|
|
129
|
-
* created once and reused on every re-render so the preview keeps its state.
|
|
130
|
-
* @param {Object.<string, any>} types
|
|
131
|
-
* @param {Object.<string, any>} entity
|
|
132
|
-
* @returns {HTMLElement}
|
|
133
|
-
*/
|
|
134
|
-
function livePreview(types, entity) {
|
|
135
|
-
if (!livePreviews.has(entity.id)) {
|
|
136
|
-
const container = document.createElement("div")
|
|
137
|
-
// The mount needs an element, but it must not become a box of its own:
|
|
138
|
-
// as a flex item it would shrink and take the primitive down with it.
|
|
139
|
-
container.style.display = "contents"
|
|
140
|
-
|
|
141
|
-
const store = createStore({ types, entities: { [entity.id]: entity } })
|
|
142
|
-
mount(store, (api) => api.render(entity.id), container)
|
|
143
|
-
livePreviews.set(entity.id, container)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return livePreviews.get(entity.id)
|
|
147
|
-
}
|
|
148
|
-
|
|
149
119
|
const carouselSlides = [
|
|
150
120
|
"#22d3ee",
|
|
151
121
|
"#4f46e5",
|
|
@@ -1542,3 +1512,35 @@ function toTitleCase(slug) {
|
|
|
1542
1512
|
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
1543
1513
|
.join(" ")
|
|
1544
1514
|
}
|
|
1515
|
+
|
|
1516
|
+
/**
|
|
1517
|
+
* Entity-driven primitives render their controls from state, so a preview
|
|
1518
|
+
* without a store freezes: a carousel arrow would recompute from the same page
|
|
1519
|
+
* forever, and a dragged divider would never move. Give each one its own store,
|
|
1520
|
+
* created once and reused on every re-render so the preview keeps its state.
|
|
1521
|
+
* @param {Object.<string, any>} types
|
|
1522
|
+
* @param {Object.<string, any>} entity
|
|
1523
|
+
* @returns {HTMLElement}
|
|
1524
|
+
*/
|
|
1525
|
+
function livePreview(types, entity) {
|
|
1526
|
+
if (!livePreviews.has(entity.id)) {
|
|
1527
|
+
const container = document.createElement("div")
|
|
1528
|
+
// The mount needs an element, but it must not become a box of its own:
|
|
1529
|
+
// as a flex item it would shrink and take the primitive down with it.
|
|
1530
|
+
container.style.display = "contents"
|
|
1531
|
+
|
|
1532
|
+
const store = createStore({ types, entities: { [entity.id]: entity } })
|
|
1533
|
+
mount(store, (api) => api.render(entity.id), container)
|
|
1534
|
+
livePreviews.set(entity.id, container)
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
return livePreviews.get(entity.id)
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
function previewRow(children) {
|
|
1541
|
+
return html`<div class="iw-primitive-preview-row">${children}</div>`
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
function previewColumn(children) {
|
|
1545
|
+
return html`<div class="iw-primitive-preview-column">${children}</div>`
|
|
1546
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Area, Chart } from "@inglorious/charts"
|
|
2
2
|
import { html } from "@inglorious/web"
|
|
3
3
|
|
|
4
|
-
import { Divider } from "../../data-display/divider"
|
|
5
|
-
import { Icon } from "../../data-display/icon"
|
|
6
|
-
import { Typography } from "../../data-display/typography"
|
|
7
|
-
import { Grid } from "../../layout/grid"
|
|
8
|
-
import { Card } from "../../surfaces/card"
|
|
4
|
+
import { Divider } from "../../data-display/divider/index.js"
|
|
5
|
+
import { Icon } from "../../data-display/icon/index.js"
|
|
6
|
+
import { Typography } from "../../data-display/typography/index.js"
|
|
7
|
+
import { Grid } from "../../layout/grid/index.js"
|
|
8
|
+
import { Card } from "../../surfaces/card/index.js"
|
|
9
9
|
|
|
10
10
|
export const SocialCard = {
|
|
11
11
|
render(entity, api) {
|
|
@@ -2,10 +2,10 @@ import moreVertOutline from "@iconify-icons/material-symbols/more-vert-outline"
|
|
|
2
2
|
import { Area, Bar, Chart, Dots, Line } from "@inglorious/charts"
|
|
3
3
|
import { html } from "@inglorious/web"
|
|
4
4
|
|
|
5
|
-
import { Button } from "../../controls/button"
|
|
6
|
-
import { Icon } from "../../data-display/icon"
|
|
7
|
-
import { Typography } from "../../data-display/typography"
|
|
8
|
-
import { Card } from "../../surfaces/card"
|
|
5
|
+
import { Button } from "../../controls/button/index.js"
|
|
6
|
+
import { Icon } from "../../data-display/icon/index.js"
|
|
7
|
+
import { Typography } from "../../data-display/typography/index.js"
|
|
8
|
+
import { Card } from "../../surfaces/card/index.js"
|
|
9
9
|
|
|
10
10
|
export const StatCard = {
|
|
11
11
|
render(entity, api) {
|
|
@@ -61,6 +61,11 @@ export function nextMode(mode) {
|
|
|
61
61
|
return MODE_CYCLE[(index + 1) % MODE_CYCLE.length]
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
export const DEFAULTS = {
|
|
65
|
+
theme: DEFAULT_THEME,
|
|
66
|
+
mode: DEFAULT_MODE,
|
|
67
|
+
}
|
|
68
|
+
|
|
64
69
|
function resolveMode(mode) {
|
|
65
70
|
if (mode !== "auto") return mode
|
|
66
71
|
return getSystemMode()
|
|
@@ -88,8 +93,3 @@ function ensureSystemListener() {
|
|
|
88
93
|
systemMedia.addListener(systemListener)
|
|
89
94
|
}
|
|
90
95
|
}
|
|
91
|
-
|
|
92
|
-
export const DEFAULTS = {
|
|
93
|
-
theme: DEFAULT_THEME,
|
|
94
|
-
mode: DEFAULT_MODE,
|
|
95
|
-
}
|
|
@@ -9,15 +9,15 @@ import {
|
|
|
9
9
|
} from "@inglorious/charts"
|
|
10
10
|
import { html } from "@inglorious/web"
|
|
11
11
|
|
|
12
|
-
import { Button } from "../../controls/button"
|
|
13
|
-
import { ButtonGroup } from "../../controls/button-group"
|
|
14
|
-
import { Icon } from "../../data-display/icon"
|
|
15
|
-
import { Typography } from "../../data-display/typography"
|
|
16
|
-
import { Progress } from "../../feedback/progress"
|
|
17
|
-
import { Flex } from "../../layout/flex"
|
|
18
|
-
import { Grid } from "../../layout/grid"
|
|
19
|
-
import { Card } from "../../surfaces/card"
|
|
20
|
-
import { trafficSeries, trafficSummary } from "./data"
|
|
12
|
+
import { Button } from "../../controls/button/index.js"
|
|
13
|
+
import { ButtonGroup } from "../../controls/button-group/index.js"
|
|
14
|
+
import { Icon } from "../../data-display/icon/index.js"
|
|
15
|
+
import { Typography } from "../../data-display/typography/index.js"
|
|
16
|
+
import { Progress } from "../../feedback/progress/index.js"
|
|
17
|
+
import { Flex } from "../../layout/flex/index.js"
|
|
18
|
+
import { Grid } from "../../layout/grid/index.js"
|
|
19
|
+
import { Card } from "../../surfaces/card/index.js"
|
|
20
|
+
import { trafficSeries, trafficSummary } from "./data.js"
|
|
21
21
|
|
|
22
22
|
export const TrafficCard = {
|
|
23
23
|
render(entity, api) {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import moreVertOutline from "@iconify-icons/material-symbols/more-vert-outline"
|
|
2
2
|
import { html } from "@inglorious/web"
|
|
3
3
|
|
|
4
|
-
import { Button } from "../../controls/button"
|
|
5
|
-
import { Avatar } from "../../data-display/avatar"
|
|
6
|
-
import { Badge } from "../../data-display/badge"
|
|
7
|
-
import { Icon } from "../../data-display/icon"
|
|
8
|
-
import { Table } from "../../data-display/table"
|
|
9
|
-
import { Typography } from "../../data-display/typography"
|
|
10
|
-
import { Progress } from "../../feedback/progress"
|
|
11
|
-
import { Flex } from "../../layout/flex"
|
|
12
|
-
import { Grid } from "../../layout/grid"
|
|
13
|
-
import { Card } from "../../surfaces/card"
|
|
14
|
-
import { clientBars, sourceBars, userRows } from "./data"
|
|
4
|
+
import { Button } from "../../controls/button/index.js"
|
|
5
|
+
import { Avatar } from "../../data-display/avatar/index.js"
|
|
6
|
+
import { Badge } from "../../data-display/badge/index.js"
|
|
7
|
+
import { Icon } from "../../data-display/icon/index.js"
|
|
8
|
+
import { Table } from "../../data-display/table/index.js"
|
|
9
|
+
import { Typography } from "../../data-display/typography/index.js"
|
|
10
|
+
import { Progress } from "../../feedback/progress/index.js"
|
|
11
|
+
import { Flex } from "../../layout/flex/index.js"
|
|
12
|
+
import { Grid } from "../../layout/grid/index.js"
|
|
13
|
+
import { Card } from "../../surfaces/card/index.js"
|
|
14
|
+
import { clientBars, sourceBars, userRows } from "./data.js"
|
|
15
15
|
|
|
16
16
|
export const TrafficSalesCard = {
|
|
17
17
|
render(entity, api) {
|
|
@@ -6,10 +6,6 @@
|
|
|
6
6
|
import { html } from "@inglorious/web"
|
|
7
7
|
import { classMap } from "@inglorious/web/directives/class-map"
|
|
8
8
|
|
|
9
|
-
function clamp(value) {
|
|
10
|
-
return Math.max(0, Math.min(100, value))
|
|
11
|
-
}
|
|
12
|
-
|
|
13
9
|
/**
|
|
14
10
|
* Renders a linear or circular progress indicator.
|
|
15
11
|
* Indeterminate mode is used when no explicit value is provided.
|
|
@@ -90,3 +86,7 @@ export function render(props) {
|
|
|
90
86
|
</div>
|
|
91
87
|
</div>`
|
|
92
88
|
}
|
|
89
|
+
|
|
90
|
+
function clamp(value) {
|
|
91
|
+
return Math.max(0, Math.min(100, value))
|
|
92
|
+
}
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
import { html } from "@inglorious/web"
|
|
7
7
|
import { when } from "@inglorious/web/directives/when"
|
|
8
8
|
|
|
9
|
-
import { Button } from "../../controls/button"
|
|
10
|
-
import { Icon } from "../../data-display/icon"
|
|
11
|
-
import { Backdrop } from "../../feedback/backdrop"
|
|
12
|
-
import { Flex } from "../../layout/flex"
|
|
9
|
+
import { Button } from "../../controls/button/index.js"
|
|
10
|
+
import { Icon } from "../../data-display/icon/index.js"
|
|
11
|
+
import { Backdrop } from "../../feedback/backdrop/index.js"
|
|
12
|
+
import { Flex } from "../../layout/flex/index.js"
|
|
13
13
|
import { close, leftPanelClose } from "../../shared/icons.js"
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
const previousKeysByElement = new WeakMap()
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Apply arbitrary properties/attributes to an element.
|
|
5
|
+
* Useful when entities include extra DOM fields beyond the typed API.
|
|
6
|
+
*
|
|
7
|
+
* @param {Element | null} element
|
|
8
|
+
* @param {Record<string, unknown>} props
|
|
9
|
+
*/
|
|
10
|
+
export function applyElementProps(element, props) {
|
|
11
|
+
if (!element) return
|
|
12
|
+
|
|
13
|
+
const previousKeys = previousKeysByElement.get(element) ?? new Set()
|
|
14
|
+
const nextKeys = new Set(Object.keys(props))
|
|
15
|
+
|
|
16
|
+
for (const key of previousKeys) {
|
|
17
|
+
if (!nextKeys.has(key)) {
|
|
18
|
+
clearProp(element, key)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
for (const [key, value] of Object.entries(props)) {
|
|
23
|
+
if (key === "class" || key === "className") continue
|
|
24
|
+
setProp(element, key, value)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
previousKeysByElement.set(element, nextKeys)
|
|
28
|
+
}
|
|
29
|
+
|
|
3
30
|
function clearProp(element, key) {
|
|
4
31
|
if (key in element && !key.includes("-")) {
|
|
5
32
|
try {
|
|
@@ -50,30 +77,3 @@ function setProp(element, key, value) {
|
|
|
50
77
|
|
|
51
78
|
element.setAttribute(key, String(value))
|
|
52
79
|
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Apply arbitrary properties/attributes to an element.
|
|
56
|
-
* Useful when entities include extra DOM fields beyond the typed API.
|
|
57
|
-
*
|
|
58
|
-
* @param {Element | null} element
|
|
59
|
-
* @param {Record<string, unknown>} props
|
|
60
|
-
*/
|
|
61
|
-
export function applyElementProps(element, props) {
|
|
62
|
-
if (!element) return
|
|
63
|
-
|
|
64
|
-
const previousKeys = previousKeysByElement.get(element) ?? new Set()
|
|
65
|
-
const nextKeys = new Set(Object.keys(props))
|
|
66
|
-
|
|
67
|
-
for (const key of previousKeys) {
|
|
68
|
-
if (!nextKeys.has(key)) {
|
|
69
|
-
clearProp(element, key)
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
for (const [key, value] of Object.entries(props)) {
|
|
74
|
-
if (key === "class" || key === "className") continue
|
|
75
|
-
setProp(element, key, value)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
previousKeysByElement.set(element, nextKeys)
|
|
79
|
-
}
|