@inglorious/ui 6.0.0 → 7.0.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 +32 -12
- package/src/controls/controls.css +3 -1
- package/src/controls/file-upload/file-upload.stories.js +93 -0
- package/src/controls/file-upload/index.js +3 -0
- package/src/controls/file-upload/style.css +99 -0
- package/src/controls/file-upload/template.js +100 -0
- package/src/controls/input/input.stories.js +110 -3
- package/src/controls/textarea/index.js +3 -0
- package/src/controls/textarea/style.css +98 -0
- package/src/controls/textarea/template.js +94 -0
- package/src/controls/textarea/textarea.stories.js +158 -0
- package/src/data-display/before-after/before-after.stories.js +74 -0
- package/src/data-display/before-after/handlers.js +44 -0
- package/src/data-display/before-after/helpers.js +4 -0
- package/src/data-display/before-after/index.js +17 -0
- package/src/data-display/before-after/style.css +128 -0
- package/src/data-display/before-after/template.js +225 -0
- package/src/data-display/carousel/carousel.stories.js +166 -0
- package/src/data-display/carousel/handlers.js +78 -0
- package/src/data-display/carousel/helpers.js +54 -0
- package/src/data-display/carousel/index.js +17 -0
- package/src/data-display/carousel/style.css +233 -0
- package/src/data-display/carousel/template.js +655 -0
- package/src/data-display/data-display.css +2 -0
- package/src/examples/dashboard/app-drawer.js +12 -0
- package/src/examples/dashboard/before-after-data.js +29 -0
- package/src/examples/dashboard/primitive-content.js +220 -33
- package/src/index.js +4 -0
- package/src/layout/flex/flex.stories.js +49 -0
- package/src/layout/flex/style.css +59 -0
- package/src/layout/flex/template.js +2 -0
- package/types/controls/file-upload.d.ts +27 -0
- package/types/controls/input.d.ts +6 -0
- package/types/controls/textarea.d.ts +29 -0
- package/types/controls/upload-field.d.ts +27 -0
- package/types/data-display/before-after.d.ts +39 -0
- package/types/data-display/carousel.d.ts +72 -0
- package/types/index.d.ts +2 -0
- package/types/layout/flex.d.ts +1 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Self-contained demo images for the Before/After control, so the dashboard
|
|
2
|
+
// renders the comparison without any network requests.
|
|
3
|
+
|
|
4
|
+
const svg = (label, from, to) =>
|
|
5
|
+
"data:image/svg+xml," +
|
|
6
|
+
encodeURIComponent(
|
|
7
|
+
`<svg xmlns="http://www.w3.org/2000/svg" width="960" height="540" viewBox="0 0 960 540">
|
|
8
|
+
<defs>
|
|
9
|
+
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1">
|
|
10
|
+
<stop offset="0" stop-color="${from}"/>
|
|
11
|
+
<stop offset="1" stop-color="${to}"/>
|
|
12
|
+
</linearGradient>
|
|
13
|
+
</defs>
|
|
14
|
+
<rect width="960" height="540" fill="url(#g)"/>
|
|
15
|
+
<text x="48" y="496" font-family="sans-serif" font-size="72" font-weight="700"
|
|
16
|
+
fill="rgba(255,255,255,0.92)">${label}</text>
|
|
17
|
+
</svg>`,
|
|
18
|
+
)
|
|
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
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createStore } from "@inglorious/store"
|
|
2
|
+
import { html, mount } from "@inglorious/web"
|
|
2
3
|
|
|
3
4
|
import { Button } from "../../controls/button/index.js"
|
|
4
5
|
import { ButtonGroup } from "../../controls/button-group/index.js"
|
|
5
6
|
import { Checkbox } from "../../controls/checkbox/index.js"
|
|
6
7
|
import { Combobox } from "../../controls/combobox/index.js"
|
|
7
8
|
import { Fab } from "../../controls/fab/index.js"
|
|
9
|
+
import { FileUpload } from "../../controls/file-upload/index.js"
|
|
8
10
|
import { IconButton } from "../../controls/icon-button/index.js"
|
|
9
11
|
import { Input } from "../../controls/input/index.js"
|
|
10
12
|
import { RadioGroup } from "../../controls/radio-group/index.js"
|
|
@@ -12,8 +14,11 @@ import { Rating } from "../../controls/rating/index.js"
|
|
|
12
14
|
import { Select } from "../../controls/select/index.js"
|
|
13
15
|
import { Slider } from "../../controls/slider/index.js"
|
|
14
16
|
import { Switch } from "../../controls/switch/index.js"
|
|
17
|
+
import { Textarea } from "../../controls/textarea/index.js"
|
|
15
18
|
import { Avatar } from "../../data-display/avatar/index.js"
|
|
16
19
|
import { Badge } from "../../data-display/badge/index.js"
|
|
20
|
+
import { BeforeAfter } from "../../data-display/before-after/index.js"
|
|
21
|
+
import { Carousel } from "../../data-display/carousel/index.js"
|
|
17
22
|
import { Chip } from "../../data-display/chip/index.js"
|
|
18
23
|
import { DataGrid } from "../../data-display/data-grid/index.js"
|
|
19
24
|
import { Divider } from "../../data-display/divider/index.js"
|
|
@@ -45,6 +50,7 @@ import { Accordion } from "../../surfaces/accordion/index.js"
|
|
|
45
50
|
import { AppBar } from "../../surfaces/app-bar/index.js"
|
|
46
51
|
import { Card } from "../../surfaces/card/index.js"
|
|
47
52
|
import { Paper } from "../../surfaces/paper/index.js"
|
|
53
|
+
import { beforeAfterImages } from "./before-after-data.js"
|
|
48
54
|
|
|
49
55
|
const categoryMeta = {
|
|
50
56
|
layout: {
|
|
@@ -102,6 +108,48 @@ const previewRow = (children) =>
|
|
|
102
108
|
const previewColumn = (children) =>
|
|
103
109
|
html`<div class="iw-primitive-preview-column">${children}</div>`
|
|
104
110
|
|
|
111
|
+
const livePreviews = new Map()
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Entity-driven primitives render their controls from state, so a preview
|
|
115
|
+
* without a store freezes: a carousel arrow would recompute from the same page
|
|
116
|
+
* forever, and a dragged divider would never move. Give each one its own store,
|
|
117
|
+
* created once and reused on every re-render so the preview keeps its state.
|
|
118
|
+
* @param {Object.<string, any>} types
|
|
119
|
+
* @param {Object.<string, any>} entity
|
|
120
|
+
* @returns {HTMLElement}
|
|
121
|
+
*/
|
|
122
|
+
function livePreview(types, entity) {
|
|
123
|
+
if (!livePreviews.has(entity.id)) {
|
|
124
|
+
const container = document.createElement("div")
|
|
125
|
+
// The mount needs an element, but it must not become a box of its own:
|
|
126
|
+
// as a flex item it would shrink and take the primitive down with it.
|
|
127
|
+
container.style.display = "contents"
|
|
128
|
+
|
|
129
|
+
const store = createStore({ types, entities: { [entity.id]: entity } })
|
|
130
|
+
mount(store, (api) => api.render(entity.id), container)
|
|
131
|
+
livePreviews.set(entity.id, container)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return livePreviews.get(entity.id)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const carouselSlides = [
|
|
138
|
+
"#22d3ee",
|
|
139
|
+
"#4f46e5",
|
|
140
|
+
"#f59e0b",
|
|
141
|
+
"#10b981",
|
|
142
|
+
"#ef4444",
|
|
143
|
+
].map(
|
|
144
|
+
(color, index) =>
|
|
145
|
+
html`<div
|
|
146
|
+
style="display:grid;place-items:center;height:14rem;border-radius:0.5rem;
|
|
147
|
+
background:${color};color:#fff;font:700 2rem sans-serif;"
|
|
148
|
+
>
|
|
149
|
+
${index + 1}
|
|
150
|
+
</div>`,
|
|
151
|
+
)
|
|
152
|
+
|
|
105
153
|
const primitiveDetailsByPath = {
|
|
106
154
|
"/layout/container": {
|
|
107
155
|
summary: "Constrains content width and applies consistent gutters.",
|
|
@@ -195,6 +243,38 @@ Grid.render({
|
|
|
195
243
|
}),
|
|
196
244
|
},
|
|
197
245
|
},
|
|
246
|
+
"/data-display/carousel": {
|
|
247
|
+
summary: "Scroll-snapping carousel with arrows and pagination dots.",
|
|
248
|
+
description:
|
|
249
|
+
"Carousel lays items out in a scroll-snapping viewport: swiping, momentum and snapping come from the browser, while the current page is the only piece of entity state. Arrows and indicators are overridable sub-renders.",
|
|
250
|
+
useCases: ["Image galleries", "Feature tours", "Onboarding slides"],
|
|
251
|
+
example: {
|
|
252
|
+
code: `import { Carousel } from "@inglorious/ui/carousel"
|
|
253
|
+
|
|
254
|
+
Carousel.render({
|
|
255
|
+
id: "demo",
|
|
256
|
+
label: "Example carousel",
|
|
257
|
+
items: [slideOne, slideTwo, slideThree],
|
|
258
|
+
page: 0,
|
|
259
|
+
gap: "md",
|
|
260
|
+
isFullWidth: true
|
|
261
|
+
})`,
|
|
262
|
+
preview: () =>
|
|
263
|
+
livePreview(
|
|
264
|
+
{ Carousel },
|
|
265
|
+
{
|
|
266
|
+
id: "carousel",
|
|
267
|
+
type: "Carousel",
|
|
268
|
+
label: "Example carousel",
|
|
269
|
+
items: carouselSlides,
|
|
270
|
+
page: 0,
|
|
271
|
+
gap: "md",
|
|
272
|
+
isInfinite: true,
|
|
273
|
+
isFullWidth: true,
|
|
274
|
+
},
|
|
275
|
+
),
|
|
276
|
+
},
|
|
277
|
+
},
|
|
198
278
|
"/controls/button": {
|
|
199
279
|
summary: "Action trigger with variants, colors, and shapes.",
|
|
200
280
|
description:
|
|
@@ -280,6 +360,36 @@ Checkbox.render({
|
|
|
280
360
|
]),
|
|
281
361
|
},
|
|
282
362
|
},
|
|
363
|
+
"/data-display/before-after": {
|
|
364
|
+
name: "Before / After",
|
|
365
|
+
summary: "Drag-to-compare slider for two overlaid images.",
|
|
366
|
+
description:
|
|
367
|
+
"Before/After overlays two images and reveals the top one with a draggable divider. The reveal is pure CSS (clip-path) and the divider position is the only piece of entity state; the divider and handle follow the active theme and color mode.",
|
|
368
|
+
useCases: ["Image comparisons", "Before/after edits", "Visual diffs"],
|
|
369
|
+
example: {
|
|
370
|
+
code: `import { BeforeAfter } from "@inglorious/ui/before-after"
|
|
371
|
+
|
|
372
|
+
BeforeAfter.render({
|
|
373
|
+
id: "demo",
|
|
374
|
+
before: { src: "before.jpg", alt: "Before" },
|
|
375
|
+
after: { src: "after.jpg", alt: "After" },
|
|
376
|
+
position: 50,
|
|
377
|
+
isFullWidth: true
|
|
378
|
+
})`,
|
|
379
|
+
preview: () =>
|
|
380
|
+
livePreview(
|
|
381
|
+
{ BeforeAfter },
|
|
382
|
+
{
|
|
383
|
+
id: "beforeAfter",
|
|
384
|
+
type: "BeforeAfter",
|
|
385
|
+
before: beforeAfterImages.before,
|
|
386
|
+
after: beforeAfterImages.after,
|
|
387
|
+
position: 50,
|
|
388
|
+
isFullWidth: true,
|
|
389
|
+
},
|
|
390
|
+
),
|
|
391
|
+
},
|
|
392
|
+
},
|
|
283
393
|
"/controls/combobox": {
|
|
284
394
|
summary: "Searchable dropdown with multi-select and tag support.",
|
|
285
395
|
description:
|
|
@@ -304,21 +414,26 @@ Combobox.render({
|
|
|
304
414
|
selectedValue: ["inglorious"]
|
|
305
415
|
})`,
|
|
306
416
|
preview: () =>
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
417
|
+
livePreview(
|
|
418
|
+
{ Combobox },
|
|
419
|
+
{
|
|
420
|
+
id: "combobox",
|
|
421
|
+
type: "Combobox",
|
|
422
|
+
label: "Frameworks",
|
|
423
|
+
placeholder: "Select frameworks...",
|
|
424
|
+
isMulti: true,
|
|
425
|
+
isSearchable: true,
|
|
426
|
+
isClearable: true,
|
|
427
|
+
options: [
|
|
428
|
+
{ label: "React", value: "react" },
|
|
429
|
+
{ label: "Angular", value: "angular" },
|
|
430
|
+
{ label: "Vue", value: "vue" },
|
|
431
|
+
{ label: "Svelte", value: "svelte" },
|
|
432
|
+
{ label: "Inglorious", value: "inglorious" },
|
|
433
|
+
],
|
|
434
|
+
selectedValue: ["inglorious"],
|
|
435
|
+
},
|
|
436
|
+
),
|
|
322
437
|
},
|
|
323
438
|
},
|
|
324
439
|
"/controls/fab": {
|
|
@@ -401,6 +516,73 @@ Input.render({
|
|
|
401
516
|
]),
|
|
402
517
|
},
|
|
403
518
|
},
|
|
519
|
+
"/controls/file-upload": {
|
|
520
|
+
summary:
|
|
521
|
+
"File selection area for uploads, attachments, and drag-and-drop flows.",
|
|
522
|
+
description:
|
|
523
|
+
"FileUpload wraps the native file input in a clearer interaction area while preserving validation, hints, and selected file summaries.",
|
|
524
|
+
useCases: ["Attachments", "Bulk upload", "Resume and invoice submissions"],
|
|
525
|
+
example: {
|
|
526
|
+
code: `import { FileUpload } from "@inglorious/ui/file-upload"
|
|
527
|
+
|
|
528
|
+
FileUpload.render({
|
|
529
|
+
label: "Resume",
|
|
530
|
+
accept: ".pdf,.doc,.docx",
|
|
531
|
+
selectedFiles: ["resume.pdf"],
|
|
532
|
+
hint: "PDF or DOCX up to 5MB"
|
|
533
|
+
})`,
|
|
534
|
+
preview: () =>
|
|
535
|
+
previewColumn([
|
|
536
|
+
FileUpload.render({
|
|
537
|
+
label: "Resume",
|
|
538
|
+
accept: ".pdf,.doc,.docx",
|
|
539
|
+
selectedFiles: ["resume.pdf"],
|
|
540
|
+
hint: "PDF or DOCX up to 5MB",
|
|
541
|
+
}),
|
|
542
|
+
FileUpload.render({
|
|
543
|
+
label: "Attachments",
|
|
544
|
+
isMultiple: true,
|
|
545
|
+
selectedFiles: ["brief.pdf", "notes.md"],
|
|
546
|
+
}),
|
|
547
|
+
]),
|
|
548
|
+
},
|
|
549
|
+
},
|
|
550
|
+
"/controls/textarea": {
|
|
551
|
+
summary: "Multi-line text entry with validation and auto-sizing support.",
|
|
552
|
+
description:
|
|
553
|
+
"Textarea is built for longer responses and keeps its height aligned with the content while supporting helper text and validation states.",
|
|
554
|
+
useCases: [
|
|
555
|
+
"Message bodies",
|
|
556
|
+
"Long-form notes",
|
|
557
|
+
"Descriptions and feedback",
|
|
558
|
+
],
|
|
559
|
+
example: {
|
|
560
|
+
code: `import { Textarea } from "@inglorious/ui/textarea"
|
|
561
|
+
|
|
562
|
+
Textarea.render({
|
|
563
|
+
label: "Project details",
|
|
564
|
+
placeholder: "Describe the scope and constraints",
|
|
565
|
+
rows: 4,
|
|
566
|
+
hint: "A few sentences are enough"
|
|
567
|
+
})`,
|
|
568
|
+
preview: () =>
|
|
569
|
+
previewColumn([
|
|
570
|
+
Textarea.render({
|
|
571
|
+
label: "Project details",
|
|
572
|
+
placeholder: "Describe the scope and constraints",
|
|
573
|
+
rows: 4,
|
|
574
|
+
hint: "A few sentences are enough",
|
|
575
|
+
value: "",
|
|
576
|
+
}),
|
|
577
|
+
Textarea.render({
|
|
578
|
+
label: "Notes",
|
|
579
|
+
value:
|
|
580
|
+
"The migration is nearly complete and we're validating the edge cases.",
|
|
581
|
+
error: "Please keep it under 280 characters.",
|
|
582
|
+
}),
|
|
583
|
+
]),
|
|
584
|
+
},
|
|
585
|
+
},
|
|
404
586
|
"/controls/radio-group": {
|
|
405
587
|
summary: "Single-choice selection among visible options.",
|
|
406
588
|
description:
|
|
@@ -590,23 +772,28 @@ DataGrid.render({
|
|
|
590
772
|
pagination: { page: 0, pageSize: 3, pageSizes: [3, 6] }
|
|
591
773
|
})`,
|
|
592
774
|
preview: () =>
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
775
|
+
livePreview(
|
|
776
|
+
{ DataGrid },
|
|
777
|
+
{
|
|
778
|
+
id: "dataGrid",
|
|
779
|
+
type: "DataGrid",
|
|
780
|
+
rowId: "id",
|
|
781
|
+
columns: [
|
|
782
|
+
{ id: "id", title: "ID", type: "number", isSortable: true },
|
|
783
|
+
{ id: "name", title: "Name" },
|
|
784
|
+
{ id: "status", title: "Status" },
|
|
785
|
+
],
|
|
786
|
+
rows: [
|
|
787
|
+
{ id: 1, name: "Alpha", status: "Active" },
|
|
788
|
+
{ id: 2, name: "Beta", status: "Paused" },
|
|
789
|
+
{ id: 3, name: "Gamma", status: "Active" },
|
|
790
|
+
],
|
|
791
|
+
filters: {},
|
|
792
|
+
sorts: [],
|
|
793
|
+
selection: [],
|
|
794
|
+
pagination: { page: 0, pageSize: 3, pageSizes: [3, 6] },
|
|
795
|
+
},
|
|
796
|
+
),
|
|
610
797
|
},
|
|
611
798
|
},
|
|
612
799
|
"/data-display/divider": {
|
package/src/index.js
CHANGED
|
@@ -9,8 +9,12 @@ export { Rating } from "./controls/rating/index.js"
|
|
|
9
9
|
export { Select } from "./controls/select/index.js"
|
|
10
10
|
export { Slider } from "./controls/slider/index.js"
|
|
11
11
|
export { Switch } from "./controls/switch/index.js"
|
|
12
|
+
export { Textarea } from "./controls/textarea/index.js"
|
|
13
|
+
export { FileUpload } from "./controls/file-upload/index.js"
|
|
12
14
|
export { Avatar } from "./data-display/avatar/index.js"
|
|
13
15
|
export { Badge } from "./data-display/badge/index.js"
|
|
16
|
+
export { BeforeAfter } from "./data-display/before-after/index.js"
|
|
17
|
+
export { Carousel } from "./data-display/carousel/index.js"
|
|
14
18
|
export { Chip } from "./data-display/chip/index.js"
|
|
15
19
|
export { DataGrid } from "./data-display/data-grid/index.js"
|
|
16
20
|
export { Divider } from "./data-display/divider/index.js"
|
|
@@ -38,6 +38,12 @@ export default {
|
|
|
38
38
|
options: ["none", "sm", "md", "lg", "xl"],
|
|
39
39
|
description: "Inner padding for the flex container.",
|
|
40
40
|
},
|
|
41
|
+
overflow: {
|
|
42
|
+
control: "select",
|
|
43
|
+
options: ["visible", "hidden", "clip", "scroll", "auto"],
|
|
44
|
+
description:
|
|
45
|
+
"Overflow behavior. Scrollable values also release flex minimum dimensions.",
|
|
46
|
+
},
|
|
41
47
|
element: {
|
|
42
48
|
control: "select",
|
|
43
49
|
options: [
|
|
@@ -84,6 +90,7 @@ Default.args = {
|
|
|
84
90
|
align: "stretch",
|
|
85
91
|
gap: "md",
|
|
86
92
|
padding: "none",
|
|
93
|
+
overflow: "visible",
|
|
87
94
|
element: "div",
|
|
88
95
|
isInline: false,
|
|
89
96
|
isFullWidth: false,
|
|
@@ -119,3 +126,45 @@ Wrapped.args = {
|
|
|
119
126
|
html`<div>Six</div>`,
|
|
120
127
|
],
|
|
121
128
|
}
|
|
129
|
+
|
|
130
|
+
export const ScrollableContent = {}
|
|
131
|
+
ScrollableContent.args = {
|
|
132
|
+
direction: "column",
|
|
133
|
+
element: "section",
|
|
134
|
+
overflow: "hidden",
|
|
135
|
+
className: "iw-flex-scrollable-story",
|
|
136
|
+
style: { height: "24rem", border: "1px solid var(--iw-color-border)" },
|
|
137
|
+
children: [
|
|
138
|
+
Flex.render({
|
|
139
|
+
element: "header",
|
|
140
|
+
padding: "md",
|
|
141
|
+
style: {
|
|
142
|
+
flex: "0 0 3.5rem",
|
|
143
|
+
background: "var(--iw-color-surface)",
|
|
144
|
+
},
|
|
145
|
+
children: ["Fixed header"],
|
|
146
|
+
}),
|
|
147
|
+
Flex.render({
|
|
148
|
+
element: "main",
|
|
149
|
+
direction: "column",
|
|
150
|
+
overflow: "auto",
|
|
151
|
+
padding: "md",
|
|
152
|
+
style: { flex: "1 1 0" },
|
|
153
|
+
children: [
|
|
154
|
+
html`<div style="min-height: 48rem">
|
|
155
|
+
This content is intentionally taller than the available space. The
|
|
156
|
+
header and footer stay visible while this main area scrolls.
|
|
157
|
+
</div>`,
|
|
158
|
+
],
|
|
159
|
+
}),
|
|
160
|
+
Flex.render({
|
|
161
|
+
element: "footer",
|
|
162
|
+
padding: "md",
|
|
163
|
+
style: {
|
|
164
|
+
flex: "0 0 3.5rem",
|
|
165
|
+
background: "var(--iw-color-surface)",
|
|
166
|
+
},
|
|
167
|
+
children: ["Fixed footer"],
|
|
168
|
+
}),
|
|
169
|
+
],
|
|
170
|
+
}
|
|
@@ -120,4 +120,63 @@
|
|
|
120
120
|
&.iw-flex-padding-xl {
|
|
121
121
|
padding: var(--iw-space-8);
|
|
122
122
|
}
|
|
123
|
+
|
|
124
|
+
/* A flex item needs both minimum dimensions released before either axis can
|
|
125
|
+
overflow instead of expanding its parent. */
|
|
126
|
+
&.iw-flex-overflow-auto,
|
|
127
|
+
&.iw-flex-overflow-scroll,
|
|
128
|
+
&.iw-flex-overflow-hidden,
|
|
129
|
+
&.iw-flex-overflow-clip {
|
|
130
|
+
min-width: 0;
|
|
131
|
+
min-height: 0;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
&.iw-flex-overflow-auto {
|
|
135
|
+
overflow: auto;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
&.iw-flex-overflow-scroll {
|
|
139
|
+
overflow: scroll;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
&.iw-flex-overflow-hidden {
|
|
143
|
+
overflow: hidden;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
&.iw-flex-overflow-clip {
|
|
147
|
+
overflow: clip;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
&.iw-flex-overflow-visible {
|
|
151
|
+
overflow: visible;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
&.iw-flex-overflow-auto,
|
|
155
|
+
&.iw-flex-overflow-scroll {
|
|
156
|
+
scrollbar-color: var(--iw-color-text-muted) var(--iw-color-surface-hover);
|
|
157
|
+
scrollbar-width: thin;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
&.iw-flex-overflow-auto::-webkit-scrollbar,
|
|
161
|
+
&.iw-flex-overflow-scroll::-webkit-scrollbar {
|
|
162
|
+
width: 0.625rem;
|
|
163
|
+
height: 0.625rem;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
&.iw-flex-overflow-auto::-webkit-scrollbar-track,
|
|
167
|
+
&.iw-flex-overflow-scroll::-webkit-scrollbar-track {
|
|
168
|
+
background: var(--iw-color-surface-hover);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
&.iw-flex-overflow-auto::-webkit-scrollbar-thumb,
|
|
172
|
+
&.iw-flex-overflow-scroll::-webkit-scrollbar-thumb {
|
|
173
|
+
border: 0.125rem solid var(--iw-color-surface-hover);
|
|
174
|
+
border-radius: var(--iw-radius-full);
|
|
175
|
+
background: var(--iw-color-text-muted);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
&.iw-flex-overflow-auto::-webkit-scrollbar-thumb:hover,
|
|
179
|
+
&.iw-flex-overflow-scroll::-webkit-scrollbar-thumb:hover {
|
|
180
|
+
background: var(--iw-color-text-secondary);
|
|
181
|
+
}
|
|
123
182
|
}
|
|
@@ -24,6 +24,7 @@ export function render(props) {
|
|
|
24
24
|
align = "stretch",
|
|
25
25
|
gap = "none",
|
|
26
26
|
padding = "none",
|
|
27
|
+
overflow = "visible",
|
|
27
28
|
isInline = false,
|
|
28
29
|
isFullWidth = false,
|
|
29
30
|
className = "",
|
|
@@ -49,6 +50,7 @@ export function render(props) {
|
|
|
49
50
|
[`iw-flex-align-${align}`]: true,
|
|
50
51
|
[`iw-flex-gap-${gap}`]: true,
|
|
51
52
|
[`iw-flex-padding-${padding}`]: true,
|
|
53
|
+
[`iw-flex-overflow-${overflow}`]: true,
|
|
52
54
|
...extraClasses,
|
|
53
55
|
}
|
|
54
56
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { TemplateResult } from "@inglorious/web"
|
|
2
|
+
|
|
3
|
+
export interface FileUploadProps {
|
|
4
|
+
id?: string
|
|
5
|
+
name?: string
|
|
6
|
+
label?: string
|
|
7
|
+
hint?: string
|
|
8
|
+
error?: string
|
|
9
|
+
accept?: string
|
|
10
|
+
isMultiple?: boolean
|
|
11
|
+
isDisabled?: boolean
|
|
12
|
+
isRequired?: boolean
|
|
13
|
+
isFullWidth?: boolean
|
|
14
|
+
selectedFiles?: string[]
|
|
15
|
+
title?: string
|
|
16
|
+
description?: string
|
|
17
|
+
onChange?: (files: FileList | null) => void
|
|
18
|
+
onBlur?: () => void
|
|
19
|
+
onFocus?: () => void
|
|
20
|
+
[key: string]: unknown
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface FileUploadType {
|
|
24
|
+
render(props: FileUploadProps): TemplateResult
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export declare const FileUpload: FileUploadType
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { TemplateResult } from "@inglorious/web"
|
|
2
|
+
|
|
3
|
+
export interface TextareaProps {
|
|
4
|
+
id?: string
|
|
5
|
+
name?: string
|
|
6
|
+
value?: string
|
|
7
|
+
placeholder?: string
|
|
8
|
+
label?: string
|
|
9
|
+
hint?: string
|
|
10
|
+
error?: string
|
|
11
|
+
size?: "sm" | "md" | "lg"
|
|
12
|
+
rows?: number
|
|
13
|
+
isDisabled?: boolean
|
|
14
|
+
isReadOnly?: boolean
|
|
15
|
+
isRequired?: boolean
|
|
16
|
+
isFullWidth?: boolean
|
|
17
|
+
isAutoSize?: boolean
|
|
18
|
+
isResizable?: boolean
|
|
19
|
+
onChange?: (value: string) => void
|
|
20
|
+
onBlur?: () => void
|
|
21
|
+
onFocus?: () => void
|
|
22
|
+
[key: string]: unknown
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface TextareaType {
|
|
26
|
+
render(props: TextareaProps): TemplateResult
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export declare const Textarea: TextareaType
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { TemplateResult } from "@inglorious/web"
|
|
2
|
+
|
|
3
|
+
export interface FileUploadProps {
|
|
4
|
+
id?: string
|
|
5
|
+
name?: string
|
|
6
|
+
label?: string
|
|
7
|
+
hint?: string
|
|
8
|
+
error?: string
|
|
9
|
+
accept?: string
|
|
10
|
+
multiple?: boolean
|
|
11
|
+
isDisabled?: boolean
|
|
12
|
+
isRequired?: boolean
|
|
13
|
+
isFullWidth?: boolean
|
|
14
|
+
selectedFiles?: string[]
|
|
15
|
+
title?: string
|
|
16
|
+
description?: string
|
|
17
|
+
onChange?: (files: FileList | null) => void
|
|
18
|
+
onBlur?: () => void
|
|
19
|
+
onFocus?: () => void
|
|
20
|
+
[key: string]: unknown
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface FileUploadType {
|
|
24
|
+
render(props: FileUploadProps): TemplateResult
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export declare const FileUpload: FileUploadType
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { TemplateResult, Api } from "@inglorious/web"
|
|
2
|
+
|
|
3
|
+
export interface BeforeAfterImage {
|
|
4
|
+
src: string
|
|
5
|
+
alt?: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface BeforeAfterProps {
|
|
9
|
+
id?: string
|
|
10
|
+
type?: string
|
|
11
|
+
label?: string
|
|
12
|
+
|
|
13
|
+
before?: BeforeAfterImage | null
|
|
14
|
+
after?: BeforeAfterImage | null
|
|
15
|
+
|
|
16
|
+
/** Divider location as a percentage (0-100). The only persistent state. */
|
|
17
|
+
position?: number
|
|
18
|
+
/** Keyboard increment, in percent, for arrow keys. */
|
|
19
|
+
step?: number
|
|
20
|
+
|
|
21
|
+
isDisabled?: boolean
|
|
22
|
+
isFullWidth?: boolean
|
|
23
|
+
|
|
24
|
+
onPositionChange?: (position: number) => void
|
|
25
|
+
[key: string]: unknown
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface BeforeAfterType {
|
|
29
|
+
create(entity: BeforeAfterProps): void
|
|
30
|
+
positionChange(entity: BeforeAfterProps, position: number): void
|
|
31
|
+
render(entity: BeforeAfterProps, api: Api): TemplateResult
|
|
32
|
+
renderBeforeAfter(props: BeforeAfterProps): TemplateResult
|
|
33
|
+
renderBefore(props: BeforeAfterProps): TemplateResult
|
|
34
|
+
renderAfter(props: BeforeAfterProps): TemplateResult
|
|
35
|
+
renderDivider(props: BeforeAfterProps): TemplateResult
|
|
36
|
+
renderHandle(props: BeforeAfterProps): TemplateResult
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export declare const BeforeAfter: BeforeAfterType
|