firstly 0.6.1 → 0.6.3
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/CHANGELOG.md +29 -0
- package/esm/svelte/FF_DialogManager.svelte +66 -46
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# firstly
|
|
2
2
|
|
|
3
|
+
## 0.6.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#298](https://github.com/jycouet/firstly/pull/298) [`626db86`](https://github.com/jycouet/firstly/commit/626db8664ddcd480bc941ba38c51aaee742188c3) Thanks [@jycouet](https://github.com/jycouet)! - fix(deps): declare `@kitql/helpers` as a runtime dependency
|
|
8
|
+
|
|
9
|
+
`esm/index.js` does `import * as h from '@kitql/helpers'` (and re-exports it /
|
|
10
|
+
builds `ff_Log` from it), but the package only listed it under
|
|
11
|
+
`devDependencies`. Consumers that didn't happen to hoist it got
|
|
12
|
+
`Cannot find module '@kitql/helpers'` at runtime. Moved it into `dependencies`.
|
|
13
|
+
|
|
14
|
+
## 0.6.2
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- [#296](https://github.com/jycouet/firstly/pull/296) [`ae7d8ec`](https://github.com/jycouet/firstly/commit/ae7d8ec532e677d42e1e5730c1ef58a29bb32062) Thanks [@jycouet](https://github.com/jycouet)! - fix(svelte): portal `FF_DialogManager` panels to `<body>`
|
|
19
|
+
|
|
20
|
+
Dialog/confirm/prompt panels rendered wherever `<FF_DialogManager>` sat in the
|
|
21
|
+
layout - inside the app root that the manager marks `inert` to trap focus. When
|
|
22
|
+
the `inert` effect won the race against the panel's autofocus, the whole panel
|
|
23
|
+
stopped receiving pointer events (real clicks died; `elementFromPoint` returned
|
|
24
|
+
`<body>`; AT saw it as "ignored"), while synthetic `.click()` still worked - so
|
|
25
|
+
it looked fine in tests but was dead under a real mouse.
|
|
26
|
+
|
|
27
|
+
Panels are now portaled to `<body>` (true siblings of the app root, matching the
|
|
28
|
+
existing design comment), so inerting the root never touches them. The
|
|
29
|
+
now-obsolete `root.contains(activeElement)` race-guard is dropped, so the
|
|
30
|
+
background is reliably inerted again.
|
|
31
|
+
|
|
3
32
|
## 0.6.1
|
|
4
33
|
|
|
5
34
|
### Patch Changes
|
|
@@ -77,19 +77,33 @@
|
|
|
77
77
|
}
|
|
78
78
|
})
|
|
79
79
|
|
|
80
|
+
// Move a dialog panel out to `<body>` so it becomes a true sibling of the app
|
|
81
|
+
// root, NOT a descendant of it. The inert effect below marks the app root
|
|
82
|
+
// `inert`; without this portal the panels render inside that root (wherever
|
|
83
|
+
// <FF_DialogManager> is mounted in the layout) and get disabled too - the
|
|
84
|
+
// panel stops receiving pointer events the moment `inert` wins the race
|
|
85
|
+
// against the panel's autofocus, so real clicks (and AT) silently die. The
|
|
86
|
+
// `portal` runs before the inner `ffAutofocus`, so focus still lands correctly.
|
|
87
|
+
function portal(node: HTMLElement) {
|
|
88
|
+
document.body.appendChild(node)
|
|
89
|
+
return {
|
|
90
|
+
destroy() {
|
|
91
|
+
node.remove()
|
|
92
|
+
},
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
80
96
|
// Mark the app root `inert` (+ aria-hidden) while any dialog is open, so the background can't
|
|
81
|
-
// be tabbed into or read by AT. The dialog panels
|
|
82
|
-
//
|
|
97
|
+
// be tabbed into or read by AT. The dialog panels are portaled to <body> (a sibling of the app
|
|
98
|
+
// root), so inerting the root never touches them - we can apply it unconditionally (no
|
|
99
|
+
// activeElement race-guard, which previously let the background stay live). SSR-safe.
|
|
83
100
|
$effect(() => {
|
|
84
101
|
if (typeof document === 'undefined' || total === 0) return
|
|
85
102
|
const root = document.querySelector<HTMLElement>(
|
|
86
103
|
'[data-sveltekit-root], #svelte, body > div:first-child',
|
|
87
104
|
)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
// inert (the per-panel focus trap still contains keyboard navigation).
|
|
91
|
-
return
|
|
92
|
-
}
|
|
105
|
+
// No identifiable single root: skip (the per-panel focus trap still contains keyboard nav).
|
|
106
|
+
if (!root) return
|
|
93
107
|
root.setAttribute('inert', '')
|
|
94
108
|
root.setAttribute('aria-hidden', 'true')
|
|
95
109
|
return () => {
|
|
@@ -112,52 +126,58 @@
|
|
|
112
126
|
{@render d.render.body(close)}
|
|
113
127
|
{/if}
|
|
114
128
|
{/snippet}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
129
|
+
<div use:portal>
|
|
130
|
+
{@render (shell ?? cfg.dialog.shell ?? defaultShell)({
|
|
131
|
+
id: d.id,
|
|
132
|
+
body: itemBody,
|
|
133
|
+
close: (r) => dialog._close(d.id, r),
|
|
134
|
+
dismiss: () => dialog.requestClose(d.id),
|
|
135
|
+
dismissible: d.options.dismissible,
|
|
136
|
+
width: d.options.width,
|
|
137
|
+
isTop: d.id === topId,
|
|
138
|
+
})}
|
|
139
|
+
</div>
|
|
124
140
|
{/each}
|
|
125
141
|
|
|
126
142
|
{#each dialog.confirmList as c (c.id)}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
143
|
+
<div use:portal>
|
|
144
|
+
{@render (confirm ?? cfg.dialog.confirm ?? defaultConfirm)({
|
|
145
|
+
id: c.id,
|
|
146
|
+
message: resolveMessage(c.message),
|
|
147
|
+
title: c.title === undefined ? undefined : resolveMessage(c.title),
|
|
148
|
+
confirmLabel: resolveMessage(c.confirmLabel ?? cfg.messages.confirm),
|
|
149
|
+
cancelLabel: resolveMessage(c.cancelLabel ?? cfg.messages.cancel),
|
|
150
|
+
danger: c.danger,
|
|
151
|
+
confirm: () => dialog._resolveConfirm(c.id, true),
|
|
152
|
+
cancel: () => dialog._resolveConfirm(c.id, false),
|
|
153
|
+
isTop: c.id === topId,
|
|
154
|
+
})}
|
|
155
|
+
</div>
|
|
138
156
|
{/each}
|
|
139
157
|
|
|
140
158
|
{#each dialog.promptList as p (p.id)}
|
|
141
159
|
{@const promptUi = prompt ?? cfg.dialog.prompt}
|
|
142
|
-
|
|
143
|
-
{
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
160
|
+
<div use:portal>
|
|
161
|
+
{#if promptUi}
|
|
162
|
+
{@render promptUi({
|
|
163
|
+
id: p.id,
|
|
164
|
+
title: p.title === undefined ? undefined : resolveMessage(p.title),
|
|
165
|
+
label: p.label === undefined ? undefined : resolveMessage(p.label),
|
|
166
|
+
placeholder: p.placeholder,
|
|
167
|
+
initial: p.initial,
|
|
168
|
+
confirmLabel: resolveMessage(p.confirmLabel ?? cfg.messages.ok),
|
|
169
|
+
cancelLabel: resolveMessage(p.cancelLabel ?? cfg.messages.cancel),
|
|
170
|
+
submit: (value) => dialog._resolvePrompt(p.id, value),
|
|
171
|
+
cancel: () => dialog._resolvePrompt(p.id, null),
|
|
172
|
+
})}
|
|
173
|
+
{:else}
|
|
174
|
+
<FF_PromptDefault
|
|
175
|
+
item={p}
|
|
176
|
+
onsubmit={(value) => dialog._resolvePrompt(p.id, value)}
|
|
177
|
+
oncancel={() => dialog._resolvePrompt(p.id, null)}
|
|
178
|
+
/>
|
|
179
|
+
{/if}
|
|
180
|
+
</div>
|
|
161
181
|
{/each}
|
|
162
182
|
|
|
163
183
|
<!-- Built-in defaults: usable with zero config and theme-adaptive via semantic tokens
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "firstly",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Firstly, an opinionated Remult setup!",
|
|
6
6
|
"funding": "https://github.com/sponsors/jycouet",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
+
"@kitql/helpers": "0.8.15",
|
|
34
35
|
"@layerstack/utils": "1.0.0",
|
|
35
36
|
"@mdi/js": "7.4.47",
|
|
36
37
|
"@types/nodemailer": "8.0.0",
|
|
@@ -39,7 +40,7 @@
|
|
|
39
40
|
"esm-env": "1.2.2",
|
|
40
41
|
"nodemailer": "8.0.5",
|
|
41
42
|
"svelte-sonner": "1.1.1",
|
|
42
|
-
"tailwind-merge": "3.
|
|
43
|
+
"tailwind-merge": "3.6.0",
|
|
43
44
|
"tailwindcss": "4.2.2",
|
|
44
45
|
"vite-plugin-kit-routes": "1.0.6",
|
|
45
46
|
"vite-plugin-stripper": "0.10.4"
|