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,113 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
id?: string;
|
|
6
|
+
label?: string;
|
|
7
|
+
value?: string | null;
|
|
8
|
+
required?: boolean;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
error?: string;
|
|
12
|
+
helpText?: string;
|
|
13
|
+
rows?: number;
|
|
14
|
+
maxlength?: number;
|
|
15
|
+
minlength?: number;
|
|
16
|
+
resize?: 'none' | 'vertical' | 'horizontal' | 'both';
|
|
17
|
+
onInput?: (value: string) => void;
|
|
18
|
+
onChange?: (value: string) => void;
|
|
19
|
+
onBlur?: () => void;
|
|
20
|
+
onFocus?: () => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let {
|
|
24
|
+
id = '',
|
|
25
|
+
label = '',
|
|
26
|
+
value = $bindable(''),
|
|
27
|
+
required = false,
|
|
28
|
+
disabled = false,
|
|
29
|
+
placeholder = '',
|
|
30
|
+
error = '',
|
|
31
|
+
helpText = '',
|
|
32
|
+
rows = 4,
|
|
33
|
+
maxlength,
|
|
34
|
+
minlength,
|
|
35
|
+
resize = 'vertical',
|
|
36
|
+
onInput,
|
|
37
|
+
onChange,
|
|
38
|
+
onBlur,
|
|
39
|
+
onFocus
|
|
40
|
+
}: Props = $props();
|
|
41
|
+
|
|
42
|
+
// Textarea wrapper class based on state
|
|
43
|
+
const wrapperClass = $derived(
|
|
44
|
+
error
|
|
45
|
+
? 'border-red-300 focus-within:border-red-500'
|
|
46
|
+
: 'border-gray-300 focus-within:border-blue-500'
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const resizeClass = {
|
|
50
|
+
none: 'resize-none',
|
|
51
|
+
vertical: 'resize-y',
|
|
52
|
+
horizontal: 'resize-x',
|
|
53
|
+
both: 'resize'
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
function handleInput(e: Event) {
|
|
57
|
+
const target = e.target as HTMLTextAreaElement;
|
|
58
|
+
value = target.value;
|
|
59
|
+
onInput?.(target.value);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function handleChange(e: Event) {
|
|
63
|
+
const target = e.target as HTMLTextAreaElement;
|
|
64
|
+
onChange?.(target.value);
|
|
65
|
+
}
|
|
66
|
+
</script>
|
|
67
|
+
|
|
68
|
+
<div class="w-full">
|
|
69
|
+
{#if label}
|
|
70
|
+
<label
|
|
71
|
+
class="mb-1.5 block text-sm font-medium text-gray-700"
|
|
72
|
+
for={id}
|
|
73
|
+
>
|
|
74
|
+
{label}
|
|
75
|
+
{#if required}
|
|
76
|
+
<span class="text-red-500 ml-0.5">*</span>
|
|
77
|
+
{/if}
|
|
78
|
+
</label>
|
|
79
|
+
{/if}
|
|
80
|
+
|
|
81
|
+
<div class="relative">
|
|
82
|
+
<div
|
|
83
|
+
class="border rounded-lg bg-white transition-all duration-200 {wrapperClass} {disabled ? 'bg-gray-50 cursor-not-allowed' : ''}"
|
|
84
|
+
>
|
|
85
|
+
<textarea
|
|
86
|
+
{id}
|
|
87
|
+
{placeholder}
|
|
88
|
+
{required}
|
|
89
|
+
{disabled}
|
|
90
|
+
{maxlength}
|
|
91
|
+
{minlength}
|
|
92
|
+
{rows}
|
|
93
|
+
bind:value
|
|
94
|
+
oninput={handleInput}
|
|
95
|
+
onchange={handleChange}
|
|
96
|
+
onblur={onBlur}
|
|
97
|
+
onfocus={onFocus}
|
|
98
|
+
class="w-full px-3 py-2 bg-transparent border-none outline-none rounded-lg focus:outline-none focus:ring-0 focus-visible:outline-none text-gray-900 placeholder-gray-400 disabled:cursor-not-allowed disabled:text-gray-500 {resizeClass[resize]}"
|
|
99
|
+
></textarea>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
{#if error}
|
|
104
|
+
<p class="mt-1.5 text-sm text-red-600 flex items-center gap-1">
|
|
105
|
+
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
|
|
106
|
+
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd"/>
|
|
107
|
+
</svg>
|
|
108
|
+
{error}
|
|
109
|
+
</p>
|
|
110
|
+
{:else if helpText}
|
|
111
|
+
<p class="mt-1.5 text-sm text-gray-500">{helpText}</p>
|
|
112
|
+
{/if}
|
|
113
|
+
</div>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
id?: string;
|
|
3
|
+
label?: string;
|
|
4
|
+
value?: string | null;
|
|
5
|
+
required?: boolean;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
error?: string;
|
|
9
|
+
helpText?: string;
|
|
10
|
+
rows?: number;
|
|
11
|
+
maxlength?: number;
|
|
12
|
+
minlength?: number;
|
|
13
|
+
resize?: 'none' | 'vertical' | 'horizontal' | 'both';
|
|
14
|
+
onInput?: (value: string) => void;
|
|
15
|
+
onChange?: (value: string) => void;
|
|
16
|
+
onBlur?: () => void;
|
|
17
|
+
onFocus?: () => void;
|
|
18
|
+
}
|
|
19
|
+
declare const TextArea: import("svelte").Component<Props, {}, "value">;
|
|
20
|
+
type TextArea = ReturnType<typeof TextArea>;
|
|
21
|
+
export default TextArea;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
export interface PreviewItem {
|
|
3
|
+
id: string;
|
|
4
|
+
title: string;
|
|
5
|
+
summary?: string;
|
|
6
|
+
image?: string;
|
|
7
|
+
date?: string;
|
|
8
|
+
href: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
items: PreviewItem[];
|
|
13
|
+
title: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
viewAllHref?: string;
|
|
16
|
+
viewAllText?: string;
|
|
17
|
+
selectedIndex?: number;
|
|
18
|
+
onSelectionChange?: (index: number) => void;
|
|
19
|
+
onItemClick?: (item: PreviewItem) => void;
|
|
20
|
+
onViewAllClick?: () => void;
|
|
21
|
+
dateLocale?: string;
|
|
22
|
+
placeholderImage?: string;
|
|
23
|
+
className?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let {
|
|
27
|
+
items = [],
|
|
28
|
+
title,
|
|
29
|
+
description,
|
|
30
|
+
viewAllHref,
|
|
31
|
+
viewAllText = "See All",
|
|
32
|
+
selectedIndex = 0,
|
|
33
|
+
onSelectionChange,
|
|
34
|
+
onItemClick,
|
|
35
|
+
onViewAllClick,
|
|
36
|
+
dateLocale = 'tr-TR',
|
|
37
|
+
placeholderImage = 'https://placehold.co/800x450',
|
|
38
|
+
className = ''
|
|
39
|
+
}: Props = $props();
|
|
40
|
+
|
|
41
|
+
let currentSelected = $state(selectedIndex);
|
|
42
|
+
|
|
43
|
+
$effect(() => {
|
|
44
|
+
currentSelected = selectedIndex;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
let selectedItem = $derived(items[currentSelected]);
|
|
48
|
+
|
|
49
|
+
function handleThumbnailClick(index: number) {
|
|
50
|
+
currentSelected = index;
|
|
51
|
+
onSelectionChange?.(index);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function handleMainItemClick() {
|
|
55
|
+
if (selectedItem) {
|
|
56
|
+
onItemClick?.(selectedItem);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function handleViewAllClick() {
|
|
61
|
+
if (onViewAllClick) {
|
|
62
|
+
onViewAllClick();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function formatDate(dateString: string): string {
|
|
67
|
+
return new Date(dateString).toLocaleDateString(dateLocale);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function getImageSrc(image?: string, isLarge: boolean = false): string {
|
|
71
|
+
if (image && image.trim()) return image;
|
|
72
|
+
return isLarge ? placeholderImage : 'https://placehold.co/256';
|
|
73
|
+
}
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
{#if items.length}
|
|
77
|
+
<div class="my-16 {className}">
|
|
78
|
+
<!-- Header -->
|
|
79
|
+
<h2 class="mb-2 text-center text-4xl font-bold text-gray-800">{title}</h2>
|
|
80
|
+
{#if description}
|
|
81
|
+
<p class="mb-12 text-center text-gray-500">{description}</p>
|
|
82
|
+
{/if}
|
|
83
|
+
|
|
84
|
+
<!-- Main Content -->
|
|
85
|
+
<div class="grid grid-cols-1 items-start gap-6 md:grid-cols-3">
|
|
86
|
+
|
|
87
|
+
<!-- Left: Preview Area (2/3 width) -->
|
|
88
|
+
<div class="md:col-span-2">
|
|
89
|
+
{#if selectedItem}
|
|
90
|
+
<button
|
|
91
|
+
type="button"
|
|
92
|
+
class="group block w-full overflow-hidden rounded-xl bg-white shadow text-left"
|
|
93
|
+
onclick={handleMainItemClick}
|
|
94
|
+
>
|
|
95
|
+
<div class="aspect-[16/9] overflow-hidden">
|
|
96
|
+
<img
|
|
97
|
+
class="h-full w-full object-cover transition-transform duration-500 group-hover:scale-[1.01]"
|
|
98
|
+
src={getImageSrc(selectedItem.image, true)}
|
|
99
|
+
alt={selectedItem.title}
|
|
100
|
+
/>
|
|
101
|
+
</div>
|
|
102
|
+
<div class="p-5">
|
|
103
|
+
{#if selectedItem.date}
|
|
104
|
+
<p class="mb-1 text-sm text-gray-500">{formatDate(selectedItem.date)}</p>
|
|
105
|
+
{/if}
|
|
106
|
+
<h3 class="text-2xl font-bold">{selectedItem.title}</h3>
|
|
107
|
+
{#if selectedItem.summary}
|
|
108
|
+
<p class="mt-2 text-gray-700">{selectedItem.summary}</p>
|
|
109
|
+
{/if}
|
|
110
|
+
</div>
|
|
111
|
+
</button>
|
|
112
|
+
{/if}
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
<!-- Right: Selector Thumbnails (1/3 width) -->
|
|
116
|
+
<div class="flex flex-col gap-3">
|
|
117
|
+
{#each items as item, index}
|
|
118
|
+
<button
|
|
119
|
+
type="button"
|
|
120
|
+
class={`group flex items-center gap-3 rounded-lg border p-2 text-left transition-shadow hover:shadow ${index === currentSelected ? 'border-blue-500 ring-2 ring-blue-200' : 'border-gray-200'}`}
|
|
121
|
+
onclick={() => handleThumbnailClick(index)}
|
|
122
|
+
aria-pressed={index === currentSelected}
|
|
123
|
+
>
|
|
124
|
+
<div class="aspect-square w-20 shrink-0 overflow-hidden rounded-md bg-gray-100">
|
|
125
|
+
<img
|
|
126
|
+
class="h-full w-full object-cover transition-transform duration-300 group-hover:scale-105"
|
|
127
|
+
src={getImageSrc(item.image)}
|
|
128
|
+
alt={item.title}
|
|
129
|
+
/>
|
|
130
|
+
</div>
|
|
131
|
+
<div class="min-w-0">
|
|
132
|
+
<h4 class="truncate font-medium text-gray-900">{item.title}</h4>
|
|
133
|
+
{#if item.date}
|
|
134
|
+
<p class="text-xs text-gray-500">{formatDate(item.date)}</p>
|
|
135
|
+
{/if}
|
|
136
|
+
</div>
|
|
137
|
+
</button>
|
|
138
|
+
{/each}
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
<!-- View All Link -->
|
|
143
|
+
{#if viewAllHref || onViewAllClick}
|
|
144
|
+
<div class="mt-6 text-right">
|
|
145
|
+
{#if viewAllHref}
|
|
146
|
+
<a
|
|
147
|
+
href={viewAllHref}
|
|
148
|
+
class="inline-flex items-center gap-1 font-medium text-blue-600 hover:text-blue-800"
|
|
149
|
+
>
|
|
150
|
+
{viewAllText} <span aria-hidden="true">→</span>
|
|
151
|
+
</a>
|
|
152
|
+
{:else if onViewAllClick}
|
|
153
|
+
<button
|
|
154
|
+
type="button"
|
|
155
|
+
onclick={handleViewAllClick}
|
|
156
|
+
class="inline-flex items-center gap-1 font-medium text-blue-600 hover:text-blue-800"
|
|
157
|
+
>
|
|
158
|
+
{viewAllText} <span aria-hidden="true">→</span>
|
|
159
|
+
</button>
|
|
160
|
+
{/if}
|
|
161
|
+
</div>
|
|
162
|
+
{/if}
|
|
163
|
+
</div>
|
|
164
|
+
{/if}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface PreviewItem {
|
|
2
|
+
id: string;
|
|
3
|
+
title: string;
|
|
4
|
+
summary?: string;
|
|
5
|
+
image?: string;
|
|
6
|
+
date?: string;
|
|
7
|
+
href: string;
|
|
8
|
+
}
|
|
9
|
+
interface Props {
|
|
10
|
+
items: PreviewItem[];
|
|
11
|
+
title: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
viewAllHref?: string;
|
|
14
|
+
viewAllText?: string;
|
|
15
|
+
selectedIndex?: number;
|
|
16
|
+
onSelectionChange?: (index: number) => void;
|
|
17
|
+
onItemClick?: (item: PreviewItem) => void;
|
|
18
|
+
onViewAllClick?: () => void;
|
|
19
|
+
dateLocale?: string;
|
|
20
|
+
placeholderImage?: string;
|
|
21
|
+
className?: string;
|
|
22
|
+
}
|
|
23
|
+
declare const PreviewSelector: import("svelte").Component<Props, {}, "">;
|
|
24
|
+
type PreviewSelector = ReturnType<typeof PreviewSelector>;
|
|
25
|
+
export default PreviewSelector;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as PreviewSelector } from './PreviewSelector.svelte';
|
package/dist/sections/index.d.ts
CHANGED
|
@@ -3,3 +3,5 @@ export { ArticlesGrid } from './ArticlesGrid';
|
|
|
3
3
|
export type { Article } from './ArticlesGrid';
|
|
4
4
|
export { FeaturedGalleryGrid } from './FeaturedGalleryGrid';
|
|
5
5
|
export type { GalleryItem } from './FeaturedGalleryGrid';
|
|
6
|
+
export { PreviewSelector } from './PreviewSelector';
|
|
7
|
+
export type { PreviewItem } from './PreviewSelector';
|
package/dist/sections/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "urpanels-ui-pack",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "Reusable Svelte 5 UI components for urPanels templates",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,6 +16,18 @@
|
|
|
16
16
|
"import": "./dist/index.js",
|
|
17
17
|
"default": "./dist/index.js"
|
|
18
18
|
},
|
|
19
|
+
"./sections": {
|
|
20
|
+
"types": "./dist/sections/index.d.ts",
|
|
21
|
+
"svelte": "./dist/sections/index.js",
|
|
22
|
+
"import": "./dist/sections/index.js",
|
|
23
|
+
"default": "./dist/sections/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./sections/*": {
|
|
26
|
+
"types": "./dist/sections/*/index.d.ts",
|
|
27
|
+
"svelte": "./dist/sections/*/index.js",
|
|
28
|
+
"import": "./dist/sections/*/index.js",
|
|
29
|
+
"default": "./dist/sections/*/index.js"
|
|
30
|
+
},
|
|
19
31
|
"./package.json": "./package.json"
|
|
20
32
|
},
|
|
21
33
|
"files": [
|
|
@@ -43,6 +55,7 @@
|
|
|
43
55
|
"@tiptap/extension-table-row": "^3.15.3",
|
|
44
56
|
"@tiptap/pm": "^3.15.3",
|
|
45
57
|
"@tiptap/starter-kit": "^3.15.3",
|
|
58
|
+
"@urga-panel/ur-panels-core": "^1.0.28",
|
|
46
59
|
"embla-carousel-svelte": "^8.5.0"
|
|
47
60
|
}
|
|
48
61
|
}
|