@widgetic/creator 0.3.49
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/README.md +116 -0
- package/dist/CreatorApp.svelte +11821 -0
- package/dist/CreatorApp.svelte.d.ts +41 -0
- package/dist/components/EditableName.svelte +94 -0
- package/dist/components/EditableName.svelte.d.ts +27 -0
- package/dist/components/SelectorDropdown.svelte +238 -0
- package/dist/components/SelectorDropdown.svelte.d.ts +41 -0
- package/dist/components/WidgetDetails.svelte +3127 -0
- package/dist/components/WidgetDetails.svelte.d.ts +235 -0
- package/dist/components/index.d.ts +0 -0
- package/dist/components/index.js +4 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +1 -0
- package/dist/creator-types.d.ts +64 -0
- package/dist/creator-types.js +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -0
- package/dist/localCacheGate.d.ts +7 -0
- package/dist/localCacheGate.js +29 -0
- package/dist/pageHelpers.d.ts +15 -0
- package/dist/pageHelpers.js +194 -0
- package/dist/stores/userSession.d.ts +7 -0
- package/dist/stores/userSession.js +32 -0
- package/dist/stores/websocketStore.d.ts +53 -0
- package/dist/stores/websocketStore.js +289 -0
- package/dist/syncSiteAuth.d.ts +9 -0
- package/dist/syncSiteAuth.js +53 -0
- package/dist/utils/creatorDraftStorage.d.ts +17 -0
- package/dist/utils/creatorDraftStorage.js +87 -0
- package/dist/utils/embedCode.d.ts +51 -0
- package/dist/utils/embedCode.js +69 -0
- package/dist/utils/models.d.ts +4 -0
- package/dist/utils/models.js +94 -0
- package/dist/utils/operationStream.d.ts +29 -0
- package/dist/utils/operationStream.js +116 -0
- package/dist/utils/prototypes.d.ts +0 -0
- package/dist/utils/prototypes.js +20 -0
- package/dist/utils/widgeticChatUpload.d.ts +26 -0
- package/dist/utils/widgeticChatUpload.js +148 -0
- package/dist/utils.d.ts +11 -0
- package/dist/utils.js +38 -0
- package/package.json +124 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { CreatorAppProps } from './creator-types.js';
|
|
2
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
|
+
$$bindings?: Bindings;
|
|
5
|
+
} & Exports;
|
|
6
|
+
(internal: unknown, props: Props & {
|
|
7
|
+
$$events?: Events;
|
|
8
|
+
$$slots?: Slots;
|
|
9
|
+
}): Exports & {
|
|
10
|
+
$set?: any;
|
|
11
|
+
$on?: any;
|
|
12
|
+
};
|
|
13
|
+
z_$$bindings?: Bindings;
|
|
14
|
+
}
|
|
15
|
+
declare const CreatorApp: $$__sveltets_2_IsomorphicComponent<{
|
|
16
|
+
/** Embedded mode props (site integration) */ embedded?: CreatorAppProps["embedded"];
|
|
17
|
+
canvasId?: CreatorAppProps["canvasId"];
|
|
18
|
+
projectId?: CreatorAppProps["projectId"];
|
|
19
|
+
workspaceType?: CreatorAppProps["workspaceType"];
|
|
20
|
+
organizationId?: CreatorAppProps["organizationId"];
|
|
21
|
+
initialWidgetId?: CreatorAppProps["initialWidgetId"];
|
|
22
|
+
initialCompositionId?: CreatorAppProps["initialCompositionId"];
|
|
23
|
+
initialStep?: CreatorAppProps["initialStep"];
|
|
24
|
+
forceCreateNewWidget?: CreatorAppProps["forceCreateNewWidget"];
|
|
25
|
+
apiUrl?: CreatorAppProps["apiUrl"];
|
|
26
|
+
widgetBuilderUrl?: CreatorAppProps["widgetBuilderUrl"];
|
|
27
|
+
initialDebugMode?: CreatorAppProps["initialDebugMode"];
|
|
28
|
+
defaultCoderModelId?: CreatorAppProps["defaultCoderModelId"];
|
|
29
|
+
defaultPlannerModelId?: CreatorAppProps["defaultPlannerModelId"];
|
|
30
|
+
showWidgetsList?: CreatorAppProps["showWidgetsList"];
|
|
31
|
+
/** Opt-in Dexie L1 — host (site / standalone) passes true. */ enableLocalCache?: CreatorAppProps["enableLocalCache"];
|
|
32
|
+
onPublishComplete?: CreatorAppProps["onPublishComplete"];
|
|
33
|
+
onBack?: CreatorAppProps["onBack"];
|
|
34
|
+
onWidgetRenamed?: CreatorAppProps["onWidgetRenamed"];
|
|
35
|
+
class?: string;
|
|
36
|
+
style?: string;
|
|
37
|
+
}, {
|
|
38
|
+
[evt: string]: CustomEvent<any>;
|
|
39
|
+
}, {}, {}, string>;
|
|
40
|
+
type CreatorApp = InstanceType<typeof CreatorApp>;
|
|
41
|
+
export default CreatorApp;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { createEventDispatcher } from 'svelte';
|
|
3
|
+
import { Tooltip } from '@widgetic/canvas/components';
|
|
4
|
+
|
|
5
|
+
export let name: string = '';
|
|
6
|
+
export let placeholder: string = 'Unnamed';
|
|
7
|
+
export let tooltipText: string = 'Double-click to rename';
|
|
8
|
+
export let tooltipPosition: 'above' | 'below' | 'left' | 'right' = 'above';
|
|
9
|
+
let className = '';
|
|
10
|
+
export { className as class };
|
|
11
|
+
export let style = '';
|
|
12
|
+
|
|
13
|
+
const dispatch = createEventDispatcher();
|
|
14
|
+
|
|
15
|
+
let isEditing = false;
|
|
16
|
+
let inputValue = '';
|
|
17
|
+
|
|
18
|
+
function startEditing() {
|
|
19
|
+
isEditing = true;
|
|
20
|
+
inputValue = name || '';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function cancelEditing() {
|
|
24
|
+
isEditing = false;
|
|
25
|
+
inputValue = '';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function commitEdit() {
|
|
29
|
+
if (!isEditing) return;
|
|
30
|
+
const trimmed = inputValue.trim();
|
|
31
|
+
isEditing = false;
|
|
32
|
+
|
|
33
|
+
if (!trimmed || trimmed === name) {
|
|
34
|
+
inputValue = '';
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
dispatch('rename', { newName: trimmed });
|
|
39
|
+
inputValue = '';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function focusAndSelect(node: HTMLInputElement, editing: boolean) {
|
|
43
|
+
function apply(shouldEdit: boolean) {
|
|
44
|
+
if (shouldEdit) {
|
|
45
|
+
requestAnimationFrame(() => {
|
|
46
|
+
node.focus();
|
|
47
|
+
node.select();
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
apply(editing);
|
|
52
|
+
return {
|
|
53
|
+
update(newEditing: boolean) {
|
|
54
|
+
apply(newEditing);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
61
|
+
<Tooltip text={isEditing ? '' : tooltipText} position={tooltipPosition}>
|
|
62
|
+
<div
|
|
63
|
+
class="editable-name-ct flex items-center gap-1 min-w-0 {className}"
|
|
64
|
+
{style}
|
|
65
|
+
ondblclick={() => startEditing()}
|
|
66
|
+
>
|
|
67
|
+
<input
|
|
68
|
+
class="editable-name-input font-semibold rounded px-1 py-0.5 text-sm outline-none transition-colors {isEditing ? 'border border-blue-400 bg-white focus:ring-1 focus:ring-blue-500' : 'border border-transparent bg-transparent cursor-default'}"
|
|
69
|
+
style="min-width: 60px; flex: 1 1 auto; {!isEditing ? 'pointer-events: none;' : ''}"
|
|
70
|
+
type="text"
|
|
71
|
+
value={isEditing ? inputValue : (name || placeholder)}
|
|
72
|
+
readonly={!isEditing}
|
|
73
|
+
tabindex={isEditing ? 0 : -1}
|
|
74
|
+
use:focusAndSelect={isEditing}
|
|
75
|
+
oninput={(e) => { if (isEditing) inputValue = e.currentTarget.value; }}
|
|
76
|
+
onkeydown={(e) => {
|
|
77
|
+
if (!isEditing) return;
|
|
78
|
+
e.stopPropagation();
|
|
79
|
+
if (e.key === 'Enter') commitEdit();
|
|
80
|
+
if (e.key === 'Escape') cancelEditing();
|
|
81
|
+
}}
|
|
82
|
+
onblur={() => { if (isEditing) commitEdit(); }}
|
|
83
|
+
/>
|
|
84
|
+
{#if !isEditing}
|
|
85
|
+
<span class="editable-name-pencil flex-shrink-0 text-gray-400 opacity-0 text-xs cursor-pointer transition-opacity">✏️</span>
|
|
86
|
+
{/if}
|
|
87
|
+
</div>
|
|
88
|
+
</Tooltip>
|
|
89
|
+
|
|
90
|
+
<style>
|
|
91
|
+
.editable-name-ct:hover .editable-name-pencil {
|
|
92
|
+
opacity: 1;
|
|
93
|
+
}
|
|
94
|
+
</style>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: Props & {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const EditableName: $$__sveltets_2_IsomorphicComponent<{
|
|
15
|
+
name?: string;
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
tooltipText?: string;
|
|
18
|
+
tooltipPosition?: "above" | "below" | "left" | "right";
|
|
19
|
+
class?: string;
|
|
20
|
+
style?: string;
|
|
21
|
+
}, {
|
|
22
|
+
rename: CustomEvent<any>;
|
|
23
|
+
} & {
|
|
24
|
+
[evt: string]: CustomEvent<any>;
|
|
25
|
+
}, {}, {}, string>;
|
|
26
|
+
type EditableName = InstanceType<typeof EditableName>;
|
|
27
|
+
export default EditableName;
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
<script lang="ts" context="module">
|
|
2
|
+
export interface DropdownItem {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
badge?: string;
|
|
6
|
+
}
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<script lang="ts">
|
|
10
|
+
/**
|
|
11
|
+
* SelectorDropdown.svelte
|
|
12
|
+
*
|
|
13
|
+
* Reusable dropdown selector (canvas-style) with:
|
|
14
|
+
* - Selected item name (click = toggle, dblclick = rename)
|
|
15
|
+
* - Chevron toggle button
|
|
16
|
+
* - "+ New" button
|
|
17
|
+
* - Dropdown list with checkbox, name, id badge, delete button
|
|
18
|
+
* - Click-outside closes
|
|
19
|
+
*/
|
|
20
|
+
import { onMount, onDestroy, tick } from 'svelte';
|
|
21
|
+
|
|
22
|
+
let className = '';
|
|
23
|
+
export { className as class };
|
|
24
|
+
export let style = '';
|
|
25
|
+
|
|
26
|
+
export let items: DropdownItem[] = [];
|
|
27
|
+
export let selectedId: string | null = null;
|
|
28
|
+
export let label = '';
|
|
29
|
+
export let labelPosition: 'above' | 'inline' = 'above';
|
|
30
|
+
export let placeholder = 'Select...';
|
|
31
|
+
export let newButtonLabel = 'New';
|
|
32
|
+
export let accentColor = '#314F2F';
|
|
33
|
+
export let nameWidth = '160px';
|
|
34
|
+
export let loading = false;
|
|
35
|
+
export let showNewButton = true;
|
|
36
|
+
export let allowRename = true;
|
|
37
|
+
|
|
38
|
+
export let onselect: ((item: DropdownItem) => void) | undefined = undefined;
|
|
39
|
+
export let ondelete: ((item: DropdownItem) => void) | undefined = undefined;
|
|
40
|
+
export let onnew: (() => void) | undefined = undefined;
|
|
41
|
+
export let onrename: ((id: string, newName: string) => void) | undefined = undefined;
|
|
42
|
+
|
|
43
|
+
let open = false;
|
|
44
|
+
let renaming = false;
|
|
45
|
+
let renameValue = '';
|
|
46
|
+
let renameInputEl: HTMLInputElement | null = null;
|
|
47
|
+
let rootEl: HTMLElement;
|
|
48
|
+
|
|
49
|
+
$: selectedItem = items.find(i => i.id === selectedId) || null;
|
|
50
|
+
$: selectedName = selectedItem?.name || placeholder;
|
|
51
|
+
|
|
52
|
+
function toggle(e: MouseEvent) {
|
|
53
|
+
e.stopPropagation();
|
|
54
|
+
if (renaming) return;
|
|
55
|
+
open = !open;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function handleSelect(item: DropdownItem, e: MouseEvent) {
|
|
59
|
+
e.stopPropagation();
|
|
60
|
+
open = false;
|
|
61
|
+
onselect?.(item);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function handleDelete(item: DropdownItem, e: MouseEvent) {
|
|
65
|
+
e.stopPropagation();
|
|
66
|
+
ondelete?.(item);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function handleNew(e: MouseEvent) {
|
|
70
|
+
e.stopPropagation();
|
|
71
|
+
open = false;
|
|
72
|
+
onnew?.();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function startRename(e: MouseEvent) {
|
|
76
|
+
e.stopPropagation();
|
|
77
|
+
if (!allowRename || !selectedItem) return;
|
|
78
|
+
renaming = true;
|
|
79
|
+
renameValue = selectedItem.name;
|
|
80
|
+
await tick();
|
|
81
|
+
renameInputEl?.focus();
|
|
82
|
+
renameInputEl?.select();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function commitRename() {
|
|
86
|
+
if (!renaming) return;
|
|
87
|
+
renaming = false;
|
|
88
|
+
if (selectedItem && renameValue.trim() && renameValue.trim() !== selectedItem.name) {
|
|
89
|
+
onrename?.(selectedItem.id, renameValue.trim());
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function handleRenameKeydown(e: KeyboardEvent) {
|
|
94
|
+
if (e.key === 'Enter') {
|
|
95
|
+
e.preventDefault();
|
|
96
|
+
commitRename();
|
|
97
|
+
} else if (e.key === 'Escape') {
|
|
98
|
+
renaming = false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function handleOutsideClick(e: MouseEvent) {
|
|
103
|
+
const target = e.target as HTMLElement;
|
|
104
|
+
if (rootEl && !rootEl.contains(target)) {
|
|
105
|
+
open = false;
|
|
106
|
+
if (renaming) commitRename();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
onMount(() => {
|
|
111
|
+
window.addEventListener('click', handleOutsideClick);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
onDestroy(() => {
|
|
115
|
+
window.removeEventListener('click', handleOutsideClick);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const accentBg = (color: string) => `rgba(${parseInt(color.slice(1,3),16)},${parseInt(color.slice(3,5),16)},${parseInt(color.slice(5,7),16)},0.08)`;
|
|
119
|
+
const accentBorder = (color: string) => `rgba(${parseInt(color.slice(1,3),16)},${parseInt(color.slice(3,5),16)},${parseInt(color.slice(5,7),16)},0.3)`;
|
|
120
|
+
</script>
|
|
121
|
+
|
|
122
|
+
<div class="selector-dropdown-group flex items-center gap-1.5 relative {className}" style="{labelPosition === 'above' ? 'padding-top: 1rem;' : ''} {style}" bind:this={rootEl}>
|
|
123
|
+
<!-- Label: above (legacy) or inline before selector -->
|
|
124
|
+
{#if label && labelPosition === 'above'}
|
|
125
|
+
<span class="selector-dropdown-label absolute top-0 left-0 pl-2 text-[10px] font-semibold uppercase tracking-wider whitespace-nowrap" style="color: {accentColor};">{label}</span>
|
|
126
|
+
{:else if label && labelPosition === 'inline'}
|
|
127
|
+
<span class="selector-dropdown-label shrink-0 text-[10px] font-semibold uppercase tracking-wider whitespace-nowrap" style="color: {accentColor};">{label}</span>
|
|
128
|
+
{/if}
|
|
129
|
+
|
|
130
|
+
<div class="selector-dropdown-area relative">
|
|
131
|
+
<!-- Selector box -->
|
|
132
|
+
<div class="selector-dropdown-box flex items-stretch border border-gray-300 rounded-md bg-white overflow-hidden transition-all {open ? 'border-gray-400' : 'hover:border-gray-400'}" style={open ? `box-shadow: 0 0 0 2px ${accentBg(accentColor)};` : ''}>
|
|
133
|
+
<div class="selector-dropdown-name flex items-center shrink-0" style="width: {nameWidth};">
|
|
134
|
+
{#if renaming}
|
|
135
|
+
<!-- svelte-ignore a11y_autofocus -->
|
|
136
|
+
<input
|
|
137
|
+
bind:this={renameInputEl}
|
|
138
|
+
bind:value={renameValue}
|
|
139
|
+
class="selector-dropdown-rename-input w-full text-[13px] font-medium text-gray-800 px-2.5 py-1 border-0 outline-none bg-transparent leading-snug"
|
|
140
|
+
onblur={commitRename}
|
|
141
|
+
onkeydown={handleRenameKeydown}
|
|
142
|
+
autofocus
|
|
143
|
+
/>
|
|
144
|
+
{:else}
|
|
145
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
146
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
147
|
+
<span
|
|
148
|
+
class="selector-dropdown-selected-text text-[13px] font-medium text-gray-800 px-2.5 py-1 cursor-pointer whitespace-nowrap overflow-hidden text-ellipsis block leading-snug"
|
|
149
|
+
style="width: {nameWidth};"
|
|
150
|
+
title={allowRename && selectedItem ? `Double-click to rename · ${selectedId || ''}` : (selectedId || '')}
|
|
151
|
+
onclick={toggle}
|
|
152
|
+
ondblclick={startRename}
|
|
153
|
+
>
|
|
154
|
+
{selectedName}{#if loading}<span class="text-gray-400 ml-1 animate-pulse text-[10px]">…</span>{/if}
|
|
155
|
+
</span>
|
|
156
|
+
{/if}
|
|
157
|
+
</div>
|
|
158
|
+
<button
|
|
159
|
+
class="selector-dropdown-trigger flex items-center justify-center w-[26px] shrink-0 border-0 border-l border-gray-200 bg-transparent cursor-pointer text-gray-500 transition-colors hover:bg-gray-200 hover:text-gray-700 {open ? 'bg-gray-200 text-gray-900' : ''}"
|
|
160
|
+
onclick={toggle}
|
|
161
|
+
title="Toggle list"
|
|
162
|
+
>
|
|
163
|
+
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" class="transition-transform {open ? 'rotate-180' : ''}">
|
|
164
|
+
<path d="M2 4l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
165
|
+
</svg>
|
|
166
|
+
</button>
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
|
|
170
|
+
<!-- "+ New" button -->
|
|
171
|
+
{#if showNewButton}
|
|
172
|
+
<button
|
|
173
|
+
class="selector-dropdown-new-btn flex items-center gap-1 px-2.5 py-1 text-xs font-medium rounded border cursor-pointer whitespace-nowrap transition-colors"
|
|
174
|
+
style="color: {accentColor}; background: {accentBg(accentColor)}; border-color: {accentBorder(accentColor)};"
|
|
175
|
+
onclick={handleNew}
|
|
176
|
+
title="{newButtonLabel}"
|
|
177
|
+
>
|
|
178
|
+
<svg width="14" height="14" viewBox="0 0 14 14" fill="none">
|
|
179
|
+
<path d="M7 2v10M2 7h10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
|
180
|
+
</svg>
|
|
181
|
+
{newButtonLabel}
|
|
182
|
+
</button>
|
|
183
|
+
{/if}
|
|
184
|
+
|
|
185
|
+
<!-- Dropdown list -->
|
|
186
|
+
{#if open}
|
|
187
|
+
<div class="selector-dropdown-list absolute top-[calc(100%+4px)] left-0 right-0 bg-white border border-gray-200 rounded-lg shadow-lg overflow-hidden p-1" style="z-index: 100;">
|
|
188
|
+
<div class="selector-dropdown-items max-h-80 overflow-y-auto overflow-x-hidden scrollbar-thin">
|
|
189
|
+
{#each items as entry (entry.id)}
|
|
190
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
191
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
192
|
+
<div
|
|
193
|
+
class="selector-dropdown-item group flex items-center gap-2 px-2 py-1.5 cursor-pointer rounded transition-colors {entry.id === selectedId ? '' : 'hover:bg-gray-50'}"
|
|
194
|
+
style={entry.id === selectedId ? `background: ${accentBg(accentColor)};` : ''}
|
|
195
|
+
onclick={(e) => handleSelect(entry, e)}
|
|
196
|
+
>
|
|
197
|
+
<!-- Checkbox -->
|
|
198
|
+
<div class="selector-dropdown-item-check shrink-0 flex items-center">
|
|
199
|
+
{#if entry.id === selectedId}
|
|
200
|
+
<svg width="12" height="12" viewBox="0 0 12 12" fill="none">
|
|
201
|
+
<rect x="1" y="1" width="10" height="10" rx="2" fill={accentColor} stroke={accentColor} stroke-width="1"/>
|
|
202
|
+
<path d="M3.5 6L5.5 8L8.5 4" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
203
|
+
</svg>
|
|
204
|
+
{:else}
|
|
205
|
+
<svg width="12" height="12" viewBox="0 0 12 12" fill="none">
|
|
206
|
+
<rect x="1.5" y="1.5" width="9" height="9" rx="1.5" stroke="#d1d5db" stroke-width="1"/>
|
|
207
|
+
</svg>
|
|
208
|
+
{/if}
|
|
209
|
+
</div>
|
|
210
|
+
<!-- Info -->
|
|
211
|
+
<div class="selector-dropdown-item-info flex flex-col flex-1 min-w-0">
|
|
212
|
+
<span class="selector-dropdown-item-name text-[13px] font-medium text-gray-900 truncate">{entry.name}</span>
|
|
213
|
+
{#if entry.badge}
|
|
214
|
+
<span class="selector-dropdown-item-badge text-[11px] text-gray-400 truncate">{entry.badge}</span>
|
|
215
|
+
{/if}
|
|
216
|
+
</div>
|
|
217
|
+
<!-- Delete -->
|
|
218
|
+
{#if ondelete}
|
|
219
|
+
<button
|
|
220
|
+
class="selector-dropdown-item-delete shrink-0 w-5 h-5 flex items-center justify-center rounded text-gray-300 hover:text-red-500 hover:bg-red-50 transition-colors"
|
|
221
|
+
title="Delete"
|
|
222
|
+
onclick={(e) => handleDelete(entry, e)}
|
|
223
|
+
>
|
|
224
|
+
<svg width="10" height="10" viewBox="0 0 10 10" fill="none">
|
|
225
|
+
<path d="M1 1L9 9M9 1L1 9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
|
226
|
+
</svg>
|
|
227
|
+
</button>
|
|
228
|
+
{/if}
|
|
229
|
+
</div>
|
|
230
|
+
{:else}
|
|
231
|
+
<div class="selector-dropdown-empty text-xs text-gray-400 px-2 py-3 text-center">
|
|
232
|
+
{loading ? 'Loading...' : 'No items found'}
|
|
233
|
+
</div>
|
|
234
|
+
{/each}
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
{/if}
|
|
238
|
+
</div>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface DropdownItem {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
badge?: string;
|
|
5
|
+
}
|
|
6
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
7
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
8
|
+
$$bindings?: Bindings;
|
|
9
|
+
} & Exports;
|
|
10
|
+
(internal: unknown, props: Props & {
|
|
11
|
+
$$events?: Events;
|
|
12
|
+
$$slots?: Slots;
|
|
13
|
+
}): Exports & {
|
|
14
|
+
$set?: any;
|
|
15
|
+
$on?: any;
|
|
16
|
+
};
|
|
17
|
+
z_$$bindings?: Bindings;
|
|
18
|
+
}
|
|
19
|
+
declare const SelectorDropdown: $$__sveltets_2_IsomorphicComponent<{
|
|
20
|
+
class?: string;
|
|
21
|
+
style?: string;
|
|
22
|
+
items?: DropdownItem[];
|
|
23
|
+
selectedId?: string | null;
|
|
24
|
+
label?: string;
|
|
25
|
+
labelPosition?: "above" | "inline";
|
|
26
|
+
placeholder?: string;
|
|
27
|
+
newButtonLabel?: string;
|
|
28
|
+
accentColor?: string;
|
|
29
|
+
nameWidth?: string;
|
|
30
|
+
loading?: boolean;
|
|
31
|
+
showNewButton?: boolean;
|
|
32
|
+
allowRename?: boolean;
|
|
33
|
+
onselect?: ((item: DropdownItem) => void) | undefined;
|
|
34
|
+
ondelete?: ((item: DropdownItem) => void) | undefined;
|
|
35
|
+
onnew?: (() => void) | undefined;
|
|
36
|
+
onrename?: ((id: string, newName: string) => void) | undefined;
|
|
37
|
+
}, {
|
|
38
|
+
[evt: string]: CustomEvent<any>;
|
|
39
|
+
}, {}, {}, string>;
|
|
40
|
+
type SelectorDropdown = InstanceType<typeof SelectorDropdown>;
|
|
41
|
+
export default SelectorDropdown;
|