urpanels-ui-pack 0.0.3 → 0.0.10
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/BasePageService/BasePageService.d.ts +121 -0
- package/dist/BasePageService/BasePageService.js +191 -0
- package/dist/BasePageService/index.d.ts +2 -0
- package/dist/BasePageService/index.js +1 -0
- package/dist/Button/Button.svelte +1 -0
- package/dist/InfoCard/InfoCard.svelte +61 -30
- package/dist/InputCheckboxModal/InputCheckboxModal.svelte +235 -0
- package/dist/InputCheckboxModal/InputCheckboxModal.svelte.d.ts +23 -0
- package/dist/InputCheckboxModal/index.d.ts +1 -0
- package/dist/InputCheckboxModal/index.js +1 -0
- package/dist/InputSelectModal/InputSelectModal.svelte +118 -0
- package/dist/InputSelectModal/InputSelectModal.svelte.d.ts +19 -0
- package/dist/InputSelectModal/index.d.ts +1 -0
- package/dist/InputSelectModal/index.js +1 -0
- package/dist/LoadingSpinner/LoadingSpinner.svelte +1 -1
- package/dist/Modal/Modal.svelte +74 -2
- package/dist/Modal/Modal.svelte.d.ts +9 -2
- package/dist/PageLayout/ActionButton.svelte +12 -4
- package/dist/PageLayout/PageContent.svelte +1 -1
- package/dist/PageLayout/PageHeader.svelte +75 -15
- package/dist/PageLayout/PageHeader.svelte.d.ts +10 -1
- package/dist/PageLayout/SearchBar.svelte +1 -1
- package/dist/PageLayout/ViewToggle.svelte +1 -1
- package/dist/Pagination/Pagination.svelte +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +8 -0
- package/dist/inputs/InputNumber/InputNumber.svelte +140 -0
- package/dist/inputs/InputNumber/InputNumber.svelte.d.ts +27 -0
- package/dist/inputs/InputNumber/index.d.ts +2 -0
- package/dist/inputs/InputNumber/index.js +2 -0
- package/dist/inputs/InputSelect/InputSelect.svelte +73 -0
- package/dist/inputs/InputSelect/InputSelect.svelte.d.ts +18 -0
- package/dist/inputs/InputSelect/index.d.ts +2 -0
- package/dist/inputs/InputSelect/index.js +2 -0
- package/dist/inputs/InputText/InputText.svelte +126 -0
- package/dist/inputs/InputText/InputText.svelte.d.ts +49 -0
- package/dist/inputs/InputText/index.d.ts +2 -0
- package/dist/inputs/InputText/index.js +2 -0
- package/dist/inputs/TextArea/TextArea.svelte +113 -0
- package/dist/inputs/TextArea/TextArea.svelte.d.ts +21 -0
- package/dist/inputs/TextArea/index.d.ts +2 -0
- package/dist/inputs/TextArea/index.js +2 -0
- package/dist/inputs/index.d.ts +3 -0
- package/dist/inputs/index.js +4 -0
- package/dist/sections/PreviewSelector/PreviewSelector.svelte +164 -0
- package/dist/sections/PreviewSelector/PreviewSelector.svelte.d.ts +25 -0
- package/dist/sections/PreviewSelector/index.d.ts +2 -0
- package/dist/sections/PreviewSelector/index.js +1 -0
- package/dist/sections/index.d.ts +2 -0
- package/dist/sections/index.js +1 -0
- package/package.json +14 -1
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { PageService, type PageOts } from "@urga-panel/ur-panels-core/dist/services/abstract/pageServices/PageServices";
|
|
2
|
+
/**
|
|
3
|
+
* View mode types for list display
|
|
4
|
+
*/
|
|
5
|
+
export type ViewMode = 'card' | 'table';
|
|
6
|
+
/**
|
|
7
|
+
* Local settings interface - extend this for custom settings
|
|
8
|
+
*/
|
|
9
|
+
export interface BaseLocalSettings {
|
|
10
|
+
viewMode?: ViewMode;
|
|
11
|
+
pageSize?: number;
|
|
12
|
+
[key: string]: any;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Base Page Service with common loading state management and local settings
|
|
16
|
+
* All page services should extend this instead of PageService directly
|
|
17
|
+
*
|
|
18
|
+
* IMPORTANT: Child classes MUST implement isLoading with $state()
|
|
19
|
+
* Example: public isLoading: boolean = $state(true);
|
|
20
|
+
*
|
|
21
|
+
* For viewMode reactivity, child class should implement:
|
|
22
|
+
* public viewMode: ViewMode = $state(this.getLocalSetting('viewMode') || 'card');
|
|
23
|
+
*/
|
|
24
|
+
export declare abstract class BasePageService extends PageService {
|
|
25
|
+
/**
|
|
26
|
+
* Loading state - MUST be implemented in child class with $state()
|
|
27
|
+
* Example: public isLoading: boolean = $state(true);
|
|
28
|
+
*/
|
|
29
|
+
abstract isLoading: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Unique key for localStorage - override in child class
|
|
32
|
+
* Default uses class name, but should be overridden for uniqueness
|
|
33
|
+
*/
|
|
34
|
+
protected get localStorageKey(): string;
|
|
35
|
+
/**
|
|
36
|
+
* Default settings - override in child class to set defaults
|
|
37
|
+
*/
|
|
38
|
+
protected get defaultSettings(): BaseLocalSettings;
|
|
39
|
+
constructor(ots: PageOts);
|
|
40
|
+
/**
|
|
41
|
+
* Wraps an async function with loading state management
|
|
42
|
+
* Automatically sets isLoading to true before execution and false after
|
|
43
|
+
*
|
|
44
|
+
* @param fn - Async function to execute
|
|
45
|
+
* @returns Promise with the result of the function
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* await service.withLoading(async () => {
|
|
49
|
+
* await loadData();
|
|
50
|
+
* });
|
|
51
|
+
*/
|
|
52
|
+
withLoading<T>(fn: () => Promise<T>): Promise<T>;
|
|
53
|
+
/**
|
|
54
|
+
* Sets loading state manually
|
|
55
|
+
* Use this when you need more granular control
|
|
56
|
+
*
|
|
57
|
+
* @param loading - Loading state
|
|
58
|
+
*/
|
|
59
|
+
protected setLoading(loading: boolean): void;
|
|
60
|
+
/**
|
|
61
|
+
* Gets all local settings from localStorage
|
|
62
|
+
* @returns Current settings merged with defaults
|
|
63
|
+
*/
|
|
64
|
+
getLocalSettings<T extends BaseLocalSettings = BaseLocalSettings>(): T;
|
|
65
|
+
/**
|
|
66
|
+
* Gets a specific setting value
|
|
67
|
+
* @param key - Setting key
|
|
68
|
+
* @returns Setting value or default
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* const viewMode = this.getLocalSetting('viewMode'); // 'card' | 'table'
|
|
72
|
+
*/
|
|
73
|
+
getLocalSetting<K extends keyof BaseLocalSettings>(key: K): BaseLocalSettings[K];
|
|
74
|
+
/**
|
|
75
|
+
* Saves a specific setting to localStorage
|
|
76
|
+
* @param key - Setting key
|
|
77
|
+
* @param value - Setting value
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* this.saveLocalSetting('viewMode', 'table');
|
|
81
|
+
*/
|
|
82
|
+
saveLocalSetting<K extends keyof BaseLocalSettings>(key: K, value: BaseLocalSettings[K]): void;
|
|
83
|
+
/**
|
|
84
|
+
* Saves multiple settings at once
|
|
85
|
+
* @param settings - Partial settings object
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* this.saveLocalSettings({ viewMode: 'table', pageSize: 50 });
|
|
89
|
+
*/
|
|
90
|
+
saveLocalSettings(settings: Partial<BaseLocalSettings>): void;
|
|
91
|
+
/**
|
|
92
|
+
* Clears all local settings for this page
|
|
93
|
+
*/
|
|
94
|
+
clearLocalSettings(): void;
|
|
95
|
+
/**
|
|
96
|
+
* Gets the current view mode from local settings
|
|
97
|
+
* @returns 'card' or 'table'
|
|
98
|
+
*/
|
|
99
|
+
getViewMode(): ViewMode;
|
|
100
|
+
/**
|
|
101
|
+
* Saves view mode preference
|
|
102
|
+
* NOTE: Child class should also update its $state viewMode property
|
|
103
|
+
* @param mode - 'card' or 'table'
|
|
104
|
+
*/
|
|
105
|
+
saveViewMode(mode: ViewMode): void;
|
|
106
|
+
/**
|
|
107
|
+
* Toggles between card and table view
|
|
108
|
+
* @returns The new view mode
|
|
109
|
+
*/
|
|
110
|
+
toggleViewMode(): ViewMode;
|
|
111
|
+
/**
|
|
112
|
+
* Gets the saved page size
|
|
113
|
+
* @returns Page size number
|
|
114
|
+
*/
|
|
115
|
+
getPageSize(): number;
|
|
116
|
+
/**
|
|
117
|
+
* Saves page size preference
|
|
118
|
+
* @param size - Number of items per page
|
|
119
|
+
*/
|
|
120
|
+
savePageSize(size: number): void;
|
|
121
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { PageService } from "@urga-panel/ur-panels-core/dist/services/abstract/pageServices/PageServices";
|
|
3
|
+
/**
|
|
4
|
+
* Base Page Service with common loading state management and local settings
|
|
5
|
+
* All page services should extend this instead of PageService directly
|
|
6
|
+
*
|
|
7
|
+
* IMPORTANT: Child classes MUST implement isLoading with $state()
|
|
8
|
+
* Example: public isLoading: boolean = $state(true);
|
|
9
|
+
*
|
|
10
|
+
* For viewMode reactivity, child class should implement:
|
|
11
|
+
* public viewMode: ViewMode = $state(this.getLocalSetting('viewMode') || 'card');
|
|
12
|
+
*/
|
|
13
|
+
export class BasePageService extends PageService {
|
|
14
|
+
/**
|
|
15
|
+
* Unique key for localStorage - override in child class
|
|
16
|
+
* Default uses class name, but should be overridden for uniqueness
|
|
17
|
+
*/
|
|
18
|
+
get localStorageKey() {
|
|
19
|
+
return `urpanels_page_${this.constructor.name}`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Default settings - override in child class to set defaults
|
|
23
|
+
*/
|
|
24
|
+
get defaultSettings() {
|
|
25
|
+
return {
|
|
26
|
+
viewMode: 'card',
|
|
27
|
+
pageSize: 20
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
constructor(ots) {
|
|
31
|
+
super(ots);
|
|
32
|
+
}
|
|
33
|
+
// ==================== Loading State Management ====================
|
|
34
|
+
/**
|
|
35
|
+
* Wraps an async function with loading state management
|
|
36
|
+
* Automatically sets isLoading to true before execution and false after
|
|
37
|
+
*
|
|
38
|
+
* @param fn - Async function to execute
|
|
39
|
+
* @returns Promise with the result of the function
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* await service.withLoading(async () => {
|
|
43
|
+
* await loadData();
|
|
44
|
+
* });
|
|
45
|
+
*/
|
|
46
|
+
async withLoading(fn) {
|
|
47
|
+
this.isLoading = true;
|
|
48
|
+
try {
|
|
49
|
+
return await fn();
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
this.isLoading = false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Sets loading state manually
|
|
57
|
+
* Use this when you need more granular control
|
|
58
|
+
*
|
|
59
|
+
* @param loading - Loading state
|
|
60
|
+
*/
|
|
61
|
+
setLoading(loading) {
|
|
62
|
+
this.isLoading = loading;
|
|
63
|
+
}
|
|
64
|
+
// ==================== Local Settings Management ====================
|
|
65
|
+
/**
|
|
66
|
+
* Gets all local settings from localStorage
|
|
67
|
+
* @returns Current settings merged with defaults
|
|
68
|
+
*/
|
|
69
|
+
getLocalSettings() {
|
|
70
|
+
if (typeof window === 'undefined') {
|
|
71
|
+
return this.defaultSettings;
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const stored = localStorage.getItem(this.localStorageKey);
|
|
75
|
+
if (stored) {
|
|
76
|
+
const parsed = JSON.parse(stored);
|
|
77
|
+
return { ...this.defaultSettings, ...parsed };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
console.warn('Failed to parse local settings:', e);
|
|
82
|
+
}
|
|
83
|
+
return this.defaultSettings;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Gets a specific setting value
|
|
87
|
+
* @param key - Setting key
|
|
88
|
+
* @returns Setting value or default
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* const viewMode = this.getLocalSetting('viewMode'); // 'card' | 'table'
|
|
92
|
+
*/
|
|
93
|
+
getLocalSetting(key) {
|
|
94
|
+
var _a;
|
|
95
|
+
const settings = this.getLocalSettings();
|
|
96
|
+
return (_a = settings[key]) !== null && _a !== void 0 ? _a : this.defaultSettings[key];
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Saves a specific setting to localStorage
|
|
100
|
+
* @param key - Setting key
|
|
101
|
+
* @param value - Setting value
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* this.saveLocalSetting('viewMode', 'table');
|
|
105
|
+
*/
|
|
106
|
+
saveLocalSetting(key, value) {
|
|
107
|
+
if (typeof window === 'undefined')
|
|
108
|
+
return;
|
|
109
|
+
try {
|
|
110
|
+
const current = this.getLocalSettings();
|
|
111
|
+
current[key] = value;
|
|
112
|
+
localStorage.setItem(this.localStorageKey, JSON.stringify(current));
|
|
113
|
+
}
|
|
114
|
+
catch (e) {
|
|
115
|
+
console.warn('Failed to save local setting:', e);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Saves multiple settings at once
|
|
120
|
+
* @param settings - Partial settings object
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* this.saveLocalSettings({ viewMode: 'table', pageSize: 50 });
|
|
124
|
+
*/
|
|
125
|
+
saveLocalSettings(settings) {
|
|
126
|
+
if (typeof window === 'undefined')
|
|
127
|
+
return;
|
|
128
|
+
try {
|
|
129
|
+
const current = this.getLocalSettings();
|
|
130
|
+
const updated = { ...current, ...settings };
|
|
131
|
+
localStorage.setItem(this.localStorageKey, JSON.stringify(updated));
|
|
132
|
+
}
|
|
133
|
+
catch (e) {
|
|
134
|
+
console.warn('Failed to save local settings:', e);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Clears all local settings for this page
|
|
139
|
+
*/
|
|
140
|
+
clearLocalSettings() {
|
|
141
|
+
if (typeof window === 'undefined')
|
|
142
|
+
return;
|
|
143
|
+
try {
|
|
144
|
+
localStorage.removeItem(this.localStorageKey);
|
|
145
|
+
}
|
|
146
|
+
catch (e) {
|
|
147
|
+
console.warn('Failed to clear local settings:', e);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// ==================== View Mode Helpers ====================
|
|
151
|
+
/**
|
|
152
|
+
* Gets the current view mode from local settings
|
|
153
|
+
* @returns 'card' or 'table'
|
|
154
|
+
*/
|
|
155
|
+
getViewMode() {
|
|
156
|
+
return this.getLocalSetting('viewMode') || 'card';
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Saves view mode preference
|
|
160
|
+
* NOTE: Child class should also update its $state viewMode property
|
|
161
|
+
* @param mode - 'card' or 'table'
|
|
162
|
+
*/
|
|
163
|
+
saveViewMode(mode) {
|
|
164
|
+
this.saveLocalSetting('viewMode', mode);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Toggles between card and table view
|
|
168
|
+
* @returns The new view mode
|
|
169
|
+
*/
|
|
170
|
+
toggleViewMode() {
|
|
171
|
+
const current = this.getViewMode();
|
|
172
|
+
const newMode = current === 'card' ? 'table' : 'card';
|
|
173
|
+
this.saveViewMode(newMode);
|
|
174
|
+
return newMode;
|
|
175
|
+
}
|
|
176
|
+
// ==================== Page Size Helpers ====================
|
|
177
|
+
/**
|
|
178
|
+
* Gets the saved page size
|
|
179
|
+
* @returns Page size number
|
|
180
|
+
*/
|
|
181
|
+
getPageSize() {
|
|
182
|
+
return this.getLocalSetting('pageSize') || 20;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Saves page size preference
|
|
186
|
+
* @param size - Number of items per page
|
|
187
|
+
*/
|
|
188
|
+
savePageSize(size) {
|
|
189
|
+
this.saveLocalSetting('pageSize', size);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { BasePageService } from './BasePageService.js';
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
badges = [],
|
|
17
17
|
relatedItems,
|
|
18
18
|
note,
|
|
19
|
+
footerActions,
|
|
19
20
|
onView,
|
|
20
21
|
onEdit,
|
|
21
22
|
onDelete
|
|
@@ -23,6 +24,7 @@
|
|
|
23
24
|
|
|
24
25
|
const isCompact = $derived(variant === 'compact');
|
|
25
26
|
const hasActions = $derived(onView || onEdit || onDelete);
|
|
27
|
+
const hasBadgeLabels = $derived(badges?.some((b) => b?.label));
|
|
26
28
|
|
|
27
29
|
function truncateText(text: string, maxLength: number): string {
|
|
28
30
|
if (!text) return '';
|
|
@@ -44,6 +46,8 @@
|
|
|
44
46
|
|
|
45
47
|
<div
|
|
46
48
|
class="bg-white rounded-lg shadow {isCompact ? 'p-3' : 'p-4'} flex flex-col gap-2 {hover ? 'hover:shadow-md transition-shadow' : ''} {className} relative"
|
|
49
|
+
data-component-name="InfoCard"
|
|
50
|
+
data-card-id={id}
|
|
47
51
|
>
|
|
48
52
|
{#if linkedStatus?.isLinked}
|
|
49
53
|
<div class="absolute -top-1 -right-1 bg-indigo-500 text-white rounded-full w-5 h-5 flex items-center justify-center shadow-sm ring-2 ring-white" title="Kullanıcı hesabına bağlı">
|
|
@@ -124,7 +128,7 @@
|
|
|
124
128
|
{#each fields as field}
|
|
125
129
|
{#if field.condition !== false}
|
|
126
130
|
<div class="{field.span === 2 ? 'col-span-2' : ''} truncate">
|
|
127
|
-
<span class="font-semibold text-gray-700">{field.label}:</span>
|
|
131
|
+
<span class="font-semibold text-gray-700 whitespace-pre-line">{field.label}:</span>
|
|
128
132
|
{#if field.icon}<span class="mx-1">{field.icon}</span>{/if}
|
|
129
133
|
<span class="text-gray-900">{field.value || '-'}</span>
|
|
130
134
|
</div>
|
|
@@ -134,38 +138,59 @@
|
|
|
134
138
|
{/if}
|
|
135
139
|
|
|
136
140
|
{#if badges && badges.length > 0}
|
|
137
|
-
{#
|
|
138
|
-
|
|
139
|
-
{#
|
|
140
|
-
{
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
141
|
+
{#if !hasBadgeLabels}
|
|
142
|
+
<div class="mt-1 flex flex-wrap gap-1">
|
|
143
|
+
{#each badges as badgeGroup}
|
|
144
|
+
{#if badgeGroup.items && badgeGroup.items.length > 0}
|
|
145
|
+
{@const displayItems = badgeGroup.maxDisplay ? badgeGroup.items.slice(0, badgeGroup.maxDisplay) : badgeGroup.items}
|
|
146
|
+
{@const remaining = badgeGroup.maxDisplay && badgeGroup.items.length > badgeGroup.maxDisplay ? badgeGroup.items.length - badgeGroup.maxDisplay : 0}
|
|
147
|
+
{#each displayItems as item}
|
|
148
|
+
<span class="{isCompact ? 'text-[10px] px-1.5 py-0.5' : 'text-xs px-2 py-1'} rounded border {getBadgeColorClasses(badgeGroup.color)}">
|
|
149
|
+
{item}
|
|
150
|
+
</span>
|
|
151
|
+
{/each}
|
|
152
|
+
{#if remaining > 0}
|
|
153
|
+
<span class="{isCompact ? 'text-[10px] px-1.5 py-0.5' : 'text-xs px-2 py-1'} rounded border {getBadgeColorClasses(badgeGroup.color)}">
|
|
154
|
+
+{remaining}
|
|
155
|
+
</span>
|
|
149
156
|
{/if}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
157
|
+
{/if}
|
|
158
|
+
{/each}
|
|
159
|
+
</div>
|
|
160
|
+
{:else}
|
|
161
|
+
{#each badges as badgeGroup}
|
|
162
|
+
{#if badgeGroup.items && badgeGroup.items.length > 0}
|
|
163
|
+
{#snippet badgeSection()}
|
|
164
|
+
{@const displayItems = badgeGroup.maxDisplay ? badgeGroup.items.slice(0, badgeGroup.maxDisplay) : badgeGroup.items}
|
|
165
|
+
{@const remaining = badgeGroup.maxDisplay && badgeGroup.items.length > badgeGroup.maxDisplay ? badgeGroup.items.length - badgeGroup.maxDisplay : 0}
|
|
166
|
+
|
|
167
|
+
<div class="mt-1">
|
|
168
|
+
{#if badgeGroup.label}
|
|
169
|
+
<div class="{isCompact ? 'text-[10px]' : 'text-xs'} font-semibold text-gray-600 mb-1">
|
|
170
|
+
{#if badgeGroup.icon}<span class="mr-1">{badgeGroup.icon}</span>{/if}
|
|
171
|
+
{badgeGroup.label}
|
|
172
|
+
</div>
|
|
161
173
|
{/if}
|
|
174
|
+
<div class="flex flex-wrap gap-1">
|
|
175
|
+
{#each displayItems as item}
|
|
176
|
+
<span class="{isCompact ? 'text-[10px] px-1.5 py-0.5' : 'text-xs px-2 py-1'} rounded border {getBadgeColorClasses(badgeGroup.color)}">
|
|
177
|
+
{item}
|
|
178
|
+
</span>
|
|
179
|
+
{/each}
|
|
180
|
+
|
|
181
|
+
{#if remaining > 0}
|
|
182
|
+
<span class="{isCompact ? 'text-[10px] px-1.5 py-0.5' : 'text-xs px-2 py-1'} rounded border {getBadgeColorClasses(badgeGroup.color)}">
|
|
183
|
+
+{remaining}
|
|
184
|
+
</span>
|
|
185
|
+
{/if}
|
|
186
|
+
</div>
|
|
162
187
|
</div>
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
{
|
|
167
|
-
{/
|
|
168
|
-
{/
|
|
188
|
+
{/snippet}
|
|
189
|
+
|
|
190
|
+
{@render badgeSection()}
|
|
191
|
+
{/if}
|
|
192
|
+
{/each}
|
|
193
|
+
{/if}
|
|
169
194
|
{/if}
|
|
170
195
|
|
|
171
196
|
{#if relatedItems && relatedItems.items && relatedItems.items.length > 0}
|
|
@@ -203,6 +228,12 @@
|
|
|
203
228
|
{note.maxLength ? truncateText(note.text, note.maxLength) : note.text}
|
|
204
229
|
</div>
|
|
205
230
|
{/if}
|
|
231
|
+
|
|
232
|
+
{#if footerActions}
|
|
233
|
+
<div class="mt-2 flex flex-wrap gap-2">
|
|
234
|
+
{@render footerActions()}
|
|
235
|
+
</div>
|
|
236
|
+
{/if}
|
|
206
237
|
|
|
207
238
|
{#if actionLayout === 'buttons' && hasActions}
|
|
208
239
|
<div class="mt-3 flex justify-end gap-2 pt-2 border-t border-gray-100">
|