@marianmeres/stuic 2.1.2 → 2.1.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/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte +4 -5
- package/dist/components/AlertConfirmPrompt/Current.svelte +43 -20
- package/dist/components/AlertConfirmPrompt/Current.svelte.d.ts +1 -2
- package/dist/components/Input/FieldOptions.svelte +41 -31
- package/dist/components/Input/FieldOptions.svelte.d.ts +6 -0
- package/dist/components/Input/index.css +2 -1
- package/package.json +4 -3
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
}
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
-
let value = $state();
|
|
31
30
|
let isPending = $state(false);
|
|
32
31
|
</script>
|
|
33
32
|
|
|
@@ -49,13 +48,13 @@
|
|
|
49
48
|
noClickOutsideClose
|
|
50
49
|
type={acp?.current?.type}
|
|
51
50
|
class={twMerge(
|
|
52
|
-
"max-w-xl justify-end max-h-[62vh]
|
|
51
|
+
"max-w-xl justify-end max-h-[62vh] h-auto border p-4 rounded-lg",
|
|
53
52
|
// different max-h based on not/existing content
|
|
54
|
-
isTHCNotEmpty(acp?.current?.content) ? "sm:max-h-[200px]" : "sm:max-h-[150px]",
|
|
55
|
-
acp?.current?.type === PROMPT && "sm:max-h-[250px]",
|
|
53
|
+
// isTHCNotEmpty(acp?.current?.content) ? "sm:max-h-[200px]" : "sm:max-h-[150px]",
|
|
54
|
+
// acp?.current?.type === PROMPT && "sm:max-h-[250px]",
|
|
56
55
|
classProp
|
|
57
56
|
)}
|
|
58
57
|
>
|
|
59
|
-
<Current bind:
|
|
58
|
+
<Current bind:isPending {acp} />
|
|
60
59
|
</ModalDialog>
|
|
61
60
|
{/if}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { tick } from "svelte";
|
|
2
3
|
import { twMerge } from "../../utils/tw-merge.js";
|
|
3
4
|
import Button from "../Button/Button.svelte";
|
|
4
5
|
import FieldInput from "../Input/FieldInput.svelte";
|
|
@@ -16,7 +17,6 @@
|
|
|
16
17
|
|
|
17
18
|
interface Props {
|
|
18
19
|
acp?: AlertConfirmPromptStack;
|
|
19
|
-
value?: any;
|
|
20
20
|
isPending?: boolean;
|
|
21
21
|
forceAsHtml?: boolean;
|
|
22
22
|
class?: string;
|
|
@@ -35,7 +35,6 @@
|
|
|
35
35
|
|
|
36
36
|
let {
|
|
37
37
|
acp,
|
|
38
|
-
value = $bindable(),
|
|
39
38
|
isPending = $bindable(false),
|
|
40
39
|
forceAsHtml = true,
|
|
41
40
|
class: classProp,
|
|
@@ -62,22 +61,35 @@
|
|
|
62
61
|
return out;
|
|
63
62
|
});
|
|
64
63
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
64
|
+
let inputEl = $state<any>();
|
|
65
|
+
let okButtonEl = $state<any>();
|
|
66
|
+
|
|
67
|
+
const createOnClick =
|
|
68
|
+
(type: "cancel" | "ok" | "custom", worker: CallableFunction) =>
|
|
69
|
+
async (e: Event | null) => {
|
|
70
|
+
e?.preventDefault();
|
|
71
|
+
|
|
72
|
+
// trigger validate
|
|
73
|
+
if (inputEl && type === "ok" && current.type === PROMPT) {
|
|
74
|
+
inputEl.dispatchEvent(new Event("input", { bubbles: true }));
|
|
75
|
+
inputEl.dispatchEvent(new Event("change", { bubbles: true }));
|
|
76
|
+
if (!inputEl.checkValidity()) return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
//
|
|
80
|
+
isPending = true;
|
|
81
|
+
await Promise.resolve(worker(current.type === PROMPT ? current.value : true));
|
|
82
|
+
isPending = false;
|
|
83
|
+
};
|
|
72
84
|
|
|
73
85
|
const debug = (c?: string, flag = 0) =>
|
|
74
86
|
c && flag ? `outline outline-dashed ${c}` : "";
|
|
75
87
|
|
|
76
88
|
// Default classes
|
|
77
89
|
|
|
78
|
-
const _class = "p-1 sm:p-2 h-full flex flex-col overflow-hidden
|
|
90
|
+
const _class = "p-1 sm:p-2 h-full flex flex-col min-h-[150px]"; // overflow-hidden
|
|
79
91
|
|
|
80
|
-
const _classWrap = `flex-1 sm:flex sm:items-start overflow-hidden
|
|
92
|
+
const _classWrap = `flex-1 sm:flex sm:items-start `; // overflow-hidden
|
|
81
93
|
|
|
82
94
|
const _classIconBox = `size-12 sm:size-10
|
|
83
95
|
mt-1 mb-4 sm:my-0 sm:mr-5
|
|
@@ -87,7 +99,7 @@
|
|
|
87
99
|
bg-neutral-950/10 text-neutral-950/80
|
|
88
100
|
dark:bg-neutral-50/20 dark:text-neutral-50/80`;
|
|
89
101
|
|
|
90
|
-
const _classContentBox = `mt-3 sm:mt-0 flex-1
|
|
102
|
+
const _classContentBox = `mt-3 sm:mt-0 flex-1 h-full flex flex-col`; // overflow-hidden
|
|
91
103
|
|
|
92
104
|
const _classTitle = `text-center sm:text-left text-base font-semibold leading-6`;
|
|
93
105
|
|
|
@@ -128,7 +140,10 @@
|
|
|
128
140
|
<Thc thc={current.title} {forceAsHtml} />
|
|
129
141
|
</h1>
|
|
130
142
|
|
|
131
|
-
<div
|
|
143
|
+
<div
|
|
144
|
+
class="scrollable overflow-y-auto flex-1 max-h-[30vh]"
|
|
145
|
+
style="scrollbar-width: thin;"
|
|
146
|
+
>
|
|
132
147
|
{#if isTHCNotEmpty(current.content)}
|
|
133
148
|
<div class={twMerge("content", _classContent, classContent)}>
|
|
134
149
|
<Thc thc={current.content} {forceAsHtml} />
|
|
@@ -136,10 +151,11 @@
|
|
|
136
151
|
{/if}
|
|
137
152
|
|
|
138
153
|
{#if current.type === PROMPT}
|
|
139
|
-
<div class={twMerge("input-box", "mt-
|
|
154
|
+
<div class={twMerge("input-box", "mt-3 p-1", classInputBox)}>
|
|
140
155
|
{#if current?.promptFieldProps?.options?.length}
|
|
141
156
|
<FieldSelect
|
|
142
|
-
bind:value
|
|
157
|
+
bind:value={current.value}
|
|
158
|
+
bind:input={inputEl}
|
|
143
159
|
class={twMerge("input", "m-0", classInput)}
|
|
144
160
|
options={current.promptFieldProps.options}
|
|
145
161
|
renderSize="sm"
|
|
@@ -148,11 +164,17 @@
|
|
|
148
164
|
/>
|
|
149
165
|
{:else}
|
|
150
166
|
<FieldInput
|
|
151
|
-
bind:value
|
|
152
|
-
|
|
167
|
+
bind:value={current.value}
|
|
168
|
+
bind:input={inputEl}
|
|
169
|
+
class={twMerge("input", "m-0", classInput)}
|
|
153
170
|
renderSize="sm"
|
|
154
171
|
disabled={isPending}
|
|
155
172
|
{...current?.promptFieldProps || {}}
|
|
173
|
+
onkeydown={(e) => {
|
|
174
|
+
if (e.key === "Enter" && inputEl.checkValidity()) {
|
|
175
|
+
okButtonEl?.focus()?.click(); // hm...
|
|
176
|
+
}
|
|
177
|
+
}}
|
|
156
178
|
/>
|
|
157
179
|
{/if}
|
|
158
180
|
</div>
|
|
@@ -166,7 +188,7 @@
|
|
|
166
188
|
<Button
|
|
167
189
|
class={twMerge("cancel", _classButton, classButton)}
|
|
168
190
|
disabled={isPending}
|
|
169
|
-
onclick={createOnClick(current.onCancel)}
|
|
191
|
+
onclick={createOnClick("cancel", current.onCancel)}
|
|
170
192
|
>
|
|
171
193
|
<Thc thc={current.labelCancel} {forceAsHtml} />
|
|
172
194
|
</Button>
|
|
@@ -177,7 +199,7 @@
|
|
|
177
199
|
<Button
|
|
178
200
|
class={twMerge("custom", _classButton, classButton)}
|
|
179
201
|
disabled={isPending}
|
|
180
|
-
onclick={createOnClick(current.onCustom)}
|
|
202
|
+
onclick={createOnClick("custom", current.onCustom)}
|
|
181
203
|
>
|
|
182
204
|
<Thc thc={current.labelCustom} {forceAsHtml} />
|
|
183
205
|
</Button>
|
|
@@ -188,7 +210,8 @@
|
|
|
188
210
|
class={twMerge("ok", _classButton, classButton)}
|
|
189
211
|
variant="primary"
|
|
190
212
|
disabled={isPending}
|
|
191
|
-
onclick={createOnClick(current.onOk)}
|
|
213
|
+
onclick={createOnClick("ok", current.onOk)}
|
|
214
|
+
bind:el={okButtonEl}
|
|
192
215
|
>
|
|
193
216
|
<Thc thc={current.labelOk} {forceAsHtml} />
|
|
194
217
|
</Button>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { type AlertConfirmPromptStack } from "./alert-confirm-prompt-stack.svelte.js";
|
|
2
2
|
interface Props {
|
|
3
3
|
acp?: AlertConfirmPromptStack;
|
|
4
|
-
value?: any;
|
|
5
4
|
isPending?: boolean;
|
|
6
5
|
forceAsHtml?: boolean;
|
|
7
6
|
class?: string;
|
|
@@ -17,6 +16,6 @@ interface Props {
|
|
|
17
16
|
classButton?: string;
|
|
18
17
|
classSpinnerBox?: string;
|
|
19
18
|
}
|
|
20
|
-
declare const Current: import("svelte").Component<Props, {}, "
|
|
19
|
+
declare const Current: import("svelte").Component<Props, {}, "isPending">;
|
|
21
20
|
type Current = ReturnType<typeof Current>;
|
|
22
21
|
export default Current;
|
|
@@ -76,6 +76,7 @@
|
|
|
76
76
|
type SnippetWithId = Snippet<[{ id: string }]>;
|
|
77
77
|
|
|
78
78
|
interface Props extends Record<string, any> {
|
|
79
|
+
trigger?: Snippet<[{ value: string; modal: Modal }]>;
|
|
79
80
|
input?: HTMLInputElement;
|
|
80
81
|
value: string;
|
|
81
82
|
label?: SnippetWithId | THC;
|
|
@@ -135,9 +136,12 @@
|
|
|
135
136
|
searchPlaceholder?: string;
|
|
136
137
|
name: string;
|
|
137
138
|
itemIdPropName?: string;
|
|
139
|
+
// for custom stuff...
|
|
140
|
+
onChange?: (value: string) => void;
|
|
138
141
|
}
|
|
139
142
|
|
|
140
143
|
let {
|
|
144
|
+
trigger,
|
|
141
145
|
input = $bindable(),
|
|
142
146
|
value = $bindable(), //
|
|
143
147
|
label = "",
|
|
@@ -191,6 +195,7 @@
|
|
|
191
195
|
searchPlaceholder,
|
|
192
196
|
name,
|
|
193
197
|
itemIdPropName = "id",
|
|
198
|
+
onChange,
|
|
194
199
|
...rest
|
|
195
200
|
}: Props = $props();
|
|
196
201
|
|
|
@@ -344,7 +349,7 @@
|
|
|
344
349
|
|
|
345
350
|
// "inner" submit
|
|
346
351
|
function try_submit(force = false) {
|
|
347
|
-
clog("try_submit", innerValue);
|
|
352
|
+
// clog("try_submit", innerValue);
|
|
348
353
|
if (innerValue) {
|
|
349
354
|
let found = have_option_label_like(_optionsColl.items, innerValue);
|
|
350
355
|
if (!found && !allowUnknown) {
|
|
@@ -396,6 +401,7 @@
|
|
|
396
401
|
_optionsColl.clear();
|
|
397
402
|
modal.close();
|
|
398
403
|
_dispatch_change_to_owner();
|
|
404
|
+
onChange?.(value);
|
|
399
405
|
}
|
|
400
406
|
|
|
401
407
|
// clears, closes, submits nothing
|
|
@@ -497,33 +503,36 @@
|
|
|
497
503
|
|
|
498
504
|
<!-- must wrap both -->
|
|
499
505
|
<div>
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
506
|
+
{#if trigger}
|
|
507
|
+
{@render trigger({ value, modal })}
|
|
508
|
+
{:else}
|
|
509
|
+
<FieldLikeButton
|
|
510
|
+
bind:value
|
|
511
|
+
bind:input={parentHiddenInputEl}
|
|
512
|
+
{name}
|
|
513
|
+
class={classProp}
|
|
514
|
+
{label}
|
|
515
|
+
{description}
|
|
516
|
+
{labelLeft}
|
|
517
|
+
{labelAfter}
|
|
518
|
+
{below}
|
|
519
|
+
{labelLeftWidth}
|
|
520
|
+
{labelLeftBreakpoint}
|
|
521
|
+
{classLabel}
|
|
522
|
+
{classLabelBox}
|
|
523
|
+
{classInputBox}
|
|
524
|
+
{classInputBoxWrap}
|
|
525
|
+
{classDescBox}
|
|
526
|
+
{classBelowBox}
|
|
527
|
+
{style}
|
|
528
|
+
validate={wrappedValidate}
|
|
529
|
+
{required}
|
|
530
|
+
{disabled}
|
|
531
|
+
renderValue={(v) => {
|
|
532
|
+
if (typeof renderValue === "function") return renderValue(v);
|
|
533
|
+
// console.log(123123, "renderValue", v);
|
|
534
|
+
// prettier-ignore
|
|
535
|
+
try {
|
|
527
536
|
// defensive
|
|
528
537
|
if (!v) v = "[]";
|
|
529
538
|
|
|
@@ -541,9 +550,10 @@
|
|
|
541
550
|
clog.warn(e);
|
|
542
551
|
return `${e}`; // either invalid json or not array...
|
|
543
552
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
553
|
+
}}
|
|
554
|
+
onclick={modal?.open}
|
|
555
|
+
/>
|
|
556
|
+
{/if}
|
|
547
557
|
|
|
548
558
|
<Modal
|
|
549
559
|
bind:this={modal}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ItemCollection, type Item } from "@marianmeres/item-collection";
|
|
2
2
|
import { type Snippet } from "svelte";
|
|
3
3
|
import { type ValidateOptions } from "../../actions/validate.svelte.js";
|
|
4
|
+
import Modal from "../Modal/Modal.svelte";
|
|
4
5
|
import { NotificationsStack } from "../Notifications/index.js";
|
|
5
6
|
import type { THC } from "../Thc/Thc.svelte";
|
|
6
7
|
import type { TranslateFn } from "../../types.js";
|
|
@@ -12,6 +13,10 @@ type SnippetWithId = Snippet<[{
|
|
|
12
13
|
id: string;
|
|
13
14
|
}]>;
|
|
14
15
|
interface Props extends Record<string, any> {
|
|
16
|
+
trigger?: Snippet<[{
|
|
17
|
+
value: string;
|
|
18
|
+
modal: Modal;
|
|
19
|
+
}]>;
|
|
15
20
|
input?: HTMLInputElement;
|
|
16
21
|
value: string;
|
|
17
22
|
label?: SnippetWithId | THC;
|
|
@@ -59,6 +64,7 @@ interface Props extends Record<string, any> {
|
|
|
59
64
|
searchPlaceholder?: string;
|
|
60
65
|
name: string;
|
|
61
66
|
itemIdPropName?: string;
|
|
67
|
+
onChange?: (value: string) => void;
|
|
62
68
|
}
|
|
63
69
|
declare const FieldOptions: import("svelte").Component<Props, {}, "value" | "input">;
|
|
64
70
|
type FieldOptions = ReturnType<typeof FieldOptions>;
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
text-base placeholder:text-base
|
|
11
11
|
bg-transparent
|
|
12
12
|
tracking-tight
|
|
13
|
-
focus:outline-
|
|
13
|
+
focus:outline-none focus:ring-0
|
|
14
|
+
focus-visible:outline-none focus-visible:ring-0
|
|
14
15
|
placeholder:tracking-tight
|
|
15
16
|
placeholder:text-neutral-950/35 dark:placeholder:text-neutral-50/35
|
|
16
17
|
text-neutral-950 dark:text-neutral-50;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@marianmeres/stuic",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "vite dev",
|
|
6
6
|
"build": "vite build && npm run prepack",
|
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
14
14
|
"format": "prettier --write .",
|
|
15
15
|
"lint": "prettier --check .",
|
|
16
|
-
"test": "vitest --dir src/"
|
|
16
|
+
"test": "vitest --dir src/",
|
|
17
|
+
"svelte-check": "svelte-check",
|
|
18
|
+
"svelte-package": "svelte-package"
|
|
17
19
|
},
|
|
18
20
|
"files": [
|
|
19
21
|
"dist",
|
|
@@ -57,7 +59,6 @@
|
|
|
57
59
|
"vite": "^6.3.6",
|
|
58
60
|
"vitest": "^3.2.4"
|
|
59
61
|
},
|
|
60
|
-
"packageManager": "pnpm@10.4.1+sha512.c753b6c3ad7afa13af388fa6d808035a008e30ea9993f58c6663e2bc5ff21679aa834db094987129aa4d488b86df57f7b634981b2f827cdcacc698cc0cfb88af",
|
|
61
62
|
"dependencies": {
|
|
62
63
|
"@marianmeres/clog": "^2.3.3",
|
|
63
64
|
"@marianmeres/item-collection": "^1.2.19",
|