@rimelight/ui 0.0.1 → 0.0.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/package.json +53 -49
- package/src/components/carousel/carousel-script.ts +188 -188
- package/src/components/carousel/index.ts +1 -1
- package/src/components/input-otp/InputOtpTypes.ts +6 -6
- package/src/components/radio-group/RadioGroupTypes.ts +6 -6
- package/src/components/select/SelectTypes.ts +13 -13
- package/src/components/switch/SwitchTypes.ts +6 -6
- package/src/components/toast/index.ts +1 -1
- package/src/components/toast/toast-manager.ts +234 -234
- package/src/components/toggle/ToggleTypes.ts +14 -14
- package/src/config/cookies.ts +5 -5
- package/src/config/index.ts +3 -3
- package/src/config/links.ts +4 -4
- package/src/config/site.config.ts +45 -45
- package/src/domain/cms/index.ts +1 -1
- package/src/domain/cms/types.ts +20 -20
- package/src/domain/i18n/constants.ts +21 -21
- package/src/domain/i18n/cookie-storage.ts +13 -13
- package/src/domain/i18n/country-to-locale-map.ts +67 -67
- package/src/domain/i18n/fetcher.ts +268 -268
- package/src/domain/i18n/flags.ts +16 -16
- package/src/domain/i18n/format.ts +90 -90
- package/src/domain/i18n/index.ts +10 -10
- package/src/domain/i18n/middleware/i18n.ts +160 -160
- package/src/domain/i18n/resolve-locale.ts +55 -55
- package/src/domain/i18n/schema.ts +29 -29
- package/src/domain/index.ts +4 -4
- package/src/domain/seo/constants.ts +20 -20
- package/src/domain/seo/index.ts +3 -3
- package/src/domain/seo/services/index.ts +3 -3
- package/src/domain/seo/services/llms.ts +53 -53
- package/src/domain/seo/services/robots.ts +12 -12
- package/src/domain/seo/services/sitemap.ts +56 -56
- package/src/domain/seo/utils.ts +37 -37
- package/src/domain/theme/constants.ts +6 -6
- package/src/domain/theme/index.ts +2 -2
- package/src/domain/theme/schema.ts +10 -10
- package/src/env.d.ts +49 -49
- package/src/integrations/index.ts +1 -0
- package/src/integrations/sri.ts +92 -0
- package/src/lib/component-preview.ts +73 -73
- package/src/lib/index.ts +6 -6
- package/src/lib/remark/remark-modified-time.ts +13 -13
- package/src/lib/showcase-preview-elements.ts +408 -408
- package/src/lib/showcase-renderer.ts +218 -218
- package/src/lib/showcase-utils.ts +189 -189
- package/src/lib/turnstile.ts +35 -35
- package/src/lib/utils/starwind/positioning.ts +318 -318
- package/src/locales/de/blog.json +9 -9
- package/src/locales/de/common.json +19 -19
- package/src/locales/de/errors.json +6 -6
- package/src/locales/de/home.json +20 -20
- package/src/locales/de/messages.json +8 -8
- package/src/locales/de/nav.json +13 -13
- package/src/locales/de/projects.json +9 -9
- package/src/locales/de/services.json +43 -43
- package/src/locales/en/blog.json +9 -9
- package/src/locales/en/chat.json +29 -29
- package/src/locales/en/common.json +19 -19
- package/src/locales/en/cookie_notice.json +11 -11
- package/src/locales/en/editor.json +24 -24
- package/src/locales/en/errors.json +6 -6
- package/src/locales/en/home.json +20 -20
- package/src/locales/en/messages.json +8 -8
- package/src/locales/en/nav.json +13 -13
- package/src/locales/en/projects.json +9 -9
- package/src/locales/en/services.json +43 -43
- package/src/locales/es/blog.json +9 -9
- package/src/locales/es/common.json +19 -19
- package/src/locales/es/errors.json +6 -6
- package/src/locales/es/home.json +20 -20
- package/src/locales/es/messages.json +8 -8
- package/src/locales/es/nav.json +13 -13
- package/src/locales/es/projects.json +9 -9
- package/src/locales/es/services.json +43 -43
- package/src/locales/ja/blog.json +9 -9
- package/src/locales/ja/common.json +19 -19
- package/src/locales/ja/errors.json +6 -6
- package/src/locales/ja/home.json +20 -20
- package/src/locales/ja/messages.json +8 -8
- package/src/locales/ja/nav.json +13 -13
- package/src/locales/ja/projects.json +9 -9
- package/src/locales/ja/services.json +43 -43
- package/src/locales/pt/blog.json +9 -9
- package/src/locales/pt/chat.json +29 -29
- package/src/locales/pt/common.json +19 -19
- package/src/locales/pt/cookie_notice.json +11 -11
- package/src/locales/pt/editor.json +24 -24
- package/src/locales/pt/errors.json +6 -6
- package/src/locales/pt/home.json +20 -20
- package/src/locales/pt/messages.json +8 -8
- package/src/locales/pt/nav.json +13 -13
- package/src/locales/pt/projects.json +9 -9
- package/src/locales/pt/services.json +43 -43
- package/src/middleware/index.ts +1 -0
- package/src/middleware/sri.ts +76 -0
- package/src/utils/index.ts +2 -2
- package/src/utils/server/cookies.ts +98 -98
- package/src/utils/server/index.ts +1 -1
- package/src/utils/shared/deep-merge.ts +36 -36
- package/src/utils/shared/embed.ts +105 -105
- package/src/utils/shared/index.ts +3 -3
- package/src/utils/shared/parse-boolean.ts +14 -14
package/package.json
CHANGED
|
@@ -1,49 +1,53 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@rimelight/ui",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Rimelight UI Library.",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"author": "Daniel Marchi",
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"./
|
|
17
|
-
"./
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"src",
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
},
|
|
34
|
-
"dependencies": {
|
|
35
|
-
"css-variants": "2.3.5",
|
|
36
|
-
"embla-carousel": "8.6.0"
|
|
37
|
-
},
|
|
38
|
-
"devDependencies": {
|
|
39
|
-
"@astrojs/check": "0.9.8",
|
|
40
|
-
"@types/node": "25.5.2",
|
|
41
|
-
"astro": "6.1.4",
|
|
42
|
-
"typescript": "6.0.2",
|
|
43
|
-
"vite-plus": "0.1.15",
|
|
44
|
-
"wrangler": "4.80.0"
|
|
45
|
-
},
|
|
46
|
-
"peerDependencies": {
|
|
47
|
-
"astro": ">=6.0.0"
|
|
48
|
-
}
|
|
49
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@rimelight/ui",
|
|
3
|
+
"version": "0.0.3",
|
|
4
|
+
"description": "Rimelight UI Library.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Daniel Marchi",
|
|
7
|
+
"files": [
|
|
8
|
+
"src",
|
|
9
|
+
"i18n-data.json",
|
|
10
|
+
"worker-configuration.d.ts",
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE"
|
|
13
|
+
],
|
|
14
|
+
"type": "module",
|
|
15
|
+
"exports": {
|
|
16
|
+
"./components/*": "./src/components/*",
|
|
17
|
+
"./config": "./src/config/index.ts",
|
|
18
|
+
"./config/*": "./src/config/*",
|
|
19
|
+
"./domain": "./src/domain/index.ts",
|
|
20
|
+
"./domain/*": "./src/domain/*",
|
|
21
|
+
"./lib": "./src/lib/index.ts",
|
|
22
|
+
"./lib/*": "./src/lib/*",
|
|
23
|
+
"./utils": "./src/utils/index.ts",
|
|
24
|
+
"./utils/*": "./src/utils/*",
|
|
25
|
+
"./integrations": "./src/integrations/index.ts",
|
|
26
|
+
"./integrations/*": "./src/integrations/*",
|
|
27
|
+
"./middleware": "./src/middleware/index.ts",
|
|
28
|
+
"./middleware/*": "./src/middleware/*",
|
|
29
|
+
"./*": "./src/*"
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"css-variants": "2.3.5",
|
|
36
|
+
"embla-carousel": "8.6.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@astrojs/check": "0.9.8",
|
|
40
|
+
"@types/node": "25.5.2",
|
|
41
|
+
"astro": "6.1.4",
|
|
42
|
+
"typescript": "6.0.2",
|
|
43
|
+
"vite-plus": "0.1.15",
|
|
44
|
+
"wrangler": "4.80.0"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"astro": ">=6.0.0"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"generate:config": "vp config",
|
|
51
|
+
"dev": "astro dev"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -1,188 +1,188 @@
|
|
|
1
|
-
import EmblaCarousel, {
|
|
2
|
-
type EmblaCarouselType,
|
|
3
|
-
type EmblaOptionsType,
|
|
4
|
-
type EmblaPluginType
|
|
5
|
-
} from "embla-carousel"
|
|
6
|
-
|
|
7
|
-
export type CarouselApi = EmblaCarouselType
|
|
8
|
-
|
|
9
|
-
export interface CarouselOptions {
|
|
10
|
-
opts?: EmblaOptionsType
|
|
11
|
-
plugins?: EmblaPluginType[]
|
|
12
|
-
setApi?: (api: CarouselApi) => void
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface CarouselManager {
|
|
16
|
-
api: CarouselApi
|
|
17
|
-
scrollPrev: () => void
|
|
18
|
-
scrollNext: () => void
|
|
19
|
-
canScrollPrev: () => boolean
|
|
20
|
-
canScrollNext: () => boolean
|
|
21
|
-
destroy: () => void
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function initCarousel(
|
|
25
|
-
carouselElement: HTMLElement,
|
|
26
|
-
options: CarouselOptions = {}
|
|
27
|
-
): CarouselManager | null {
|
|
28
|
-
// don't re-initialize if already initialized
|
|
29
|
-
if (carouselElement.dataset.initialized === "true") return null
|
|
30
|
-
carouselElement.dataset.initialized = "true"
|
|
31
|
-
|
|
32
|
-
if (!carouselElement) {
|
|
33
|
-
console.warn("Carousel element not found")
|
|
34
|
-
return null
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Find content element - Embla expects the viewport element, not the container
|
|
38
|
-
const viewportElement = carouselElement.querySelector('[data-slot="carousel-content"]')
|
|
39
|
-
|
|
40
|
-
if (!(viewportElement instanceof HTMLElement)) {
|
|
41
|
-
console.warn("Carousel content element not found")
|
|
42
|
-
return null
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Get configuration from data attributes
|
|
46
|
-
const axisData = carouselElement.dataset.axis
|
|
47
|
-
const axis: EmblaOptionsType["axis"] = axisData === "y" ? "y" : "x"
|
|
48
|
-
|
|
49
|
-
// Safely parse data options
|
|
50
|
-
let dataOpts = {}
|
|
51
|
-
try {
|
|
52
|
-
const optsString = carouselElement.dataset.opts
|
|
53
|
-
if (optsString && optsString !== "undefined" && optsString !== "null") {
|
|
54
|
-
dataOpts = JSON.parse(optsString)
|
|
55
|
-
}
|
|
56
|
-
} catch (e) {
|
|
57
|
-
console.warn("Failed to parse carousel opts:", e)
|
|
58
|
-
dataOpts = {}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Ensure dataOpts is a valid object
|
|
62
|
-
if (!dataOpts || typeof dataOpts !== "object") {
|
|
63
|
-
dataOpts = {}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Merge options - ensure we always have a valid object
|
|
67
|
-
const emblaOptions: EmblaOptionsType = {
|
|
68
|
-
axis,
|
|
69
|
-
...dataOpts,
|
|
70
|
-
...options.opts
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Handle plugins - EmblaCarousel expects undefined when no plugins, not empty array
|
|
74
|
-
const plugins = options.plugins && options.plugins.length > 0 ? options.plugins : undefined
|
|
75
|
-
|
|
76
|
-
// console.log("ID:", carouselElement.id);
|
|
77
|
-
// console.log("Plugins:", plugins);
|
|
78
|
-
// console.log("Options:", emblaOptions);
|
|
79
|
-
|
|
80
|
-
// Find navigation buttons
|
|
81
|
-
const prevButton = carouselElement.querySelector(".starwind-carousel-previous")
|
|
82
|
-
const nextButton = carouselElement.querySelector(".starwind-carousel-next")
|
|
83
|
-
|
|
84
|
-
const prevButtonEl = prevButton instanceof HTMLButtonElement ? prevButton : null
|
|
85
|
-
const nextButtonEl = nextButton instanceof HTMLButtonElement ? nextButton : null
|
|
86
|
-
|
|
87
|
-
// Initialize Embla
|
|
88
|
-
let emblaApi: EmblaCarouselType
|
|
89
|
-
if (plugins) {
|
|
90
|
-
emblaApi = EmblaCarousel(viewportElement, emblaOptions, plugins)
|
|
91
|
-
} else {
|
|
92
|
-
emblaApi = EmblaCarousel(viewportElement, emblaOptions)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Update button states
|
|
96
|
-
const updateButtons = () => {
|
|
97
|
-
const canScrollPrev = emblaApi.canScrollPrev()
|
|
98
|
-
const canScrollNext = emblaApi.canScrollNext()
|
|
99
|
-
|
|
100
|
-
if (prevButtonEl) {
|
|
101
|
-
prevButtonEl.disabled = !canScrollPrev
|
|
102
|
-
prevButtonEl.setAttribute("aria-disabled", (!canScrollPrev).toString())
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (nextButtonEl) {
|
|
106
|
-
nextButtonEl.disabled = !canScrollNext
|
|
107
|
-
nextButtonEl.setAttribute("aria-disabled", (!canScrollNext).toString())
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Event handlers for cleanup
|
|
112
|
-
const prevClickHandler = () => emblaApi.scrollPrev()
|
|
113
|
-
const nextClickHandler = () => emblaApi.scrollNext()
|
|
114
|
-
const keydownHandler = (event: KeyboardEvent) => {
|
|
115
|
-
if (axis === "y") {
|
|
116
|
-
// Vertical axis: ArrowUp = previous, ArrowDown = next
|
|
117
|
-
if (event.key === "ArrowUp") {
|
|
118
|
-
event.preventDefault()
|
|
119
|
-
emblaApi.scrollPrev()
|
|
120
|
-
} else if (event.key === "ArrowDown") {
|
|
121
|
-
event.preventDefault()
|
|
122
|
-
emblaApi.scrollNext()
|
|
123
|
-
}
|
|
124
|
-
} else {
|
|
125
|
-
// Horizontal axis (default): ArrowLeft = previous, ArrowRight = next
|
|
126
|
-
if (event.key === "ArrowLeft") {
|
|
127
|
-
event.preventDefault()
|
|
128
|
-
emblaApi.scrollPrev()
|
|
129
|
-
} else if (event.key === "ArrowRight") {
|
|
130
|
-
event.preventDefault()
|
|
131
|
-
emblaApi.scrollNext()
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Setup event listeners
|
|
137
|
-
const setupEventListeners = () => {
|
|
138
|
-
// Navigation button listeners
|
|
139
|
-
prevButtonEl?.addEventListener("click", prevClickHandler)
|
|
140
|
-
nextButtonEl?.addEventListener("click", nextClickHandler)
|
|
141
|
-
|
|
142
|
-
// Keyboard navigation
|
|
143
|
-
carouselElement.addEventListener("keydown", keydownHandler)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Setup user API callback
|
|
147
|
-
const setupUserCallbacks = () => {
|
|
148
|
-
if (options.setApi) {
|
|
149
|
-
options.setApi(emblaApi)
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Initialize everything
|
|
154
|
-
updateButtons()
|
|
155
|
-
setupEventListeners()
|
|
156
|
-
setupUserCallbacks()
|
|
157
|
-
|
|
158
|
-
// Setup internal event listeners
|
|
159
|
-
emblaApi.on("select", updateButtons)
|
|
160
|
-
emblaApi.on("init", () => {
|
|
161
|
-
updateButtons()
|
|
162
|
-
})
|
|
163
|
-
emblaApi.on("reInit", () => {
|
|
164
|
-
updateButtons()
|
|
165
|
-
})
|
|
166
|
-
|
|
167
|
-
// Return manager interface
|
|
168
|
-
return {
|
|
169
|
-
api: emblaApi,
|
|
170
|
-
scrollPrev: () => emblaApi.scrollPrev(),
|
|
171
|
-
scrollNext: () => emblaApi.scrollNext(),
|
|
172
|
-
canScrollPrev: () => emblaApi.canScrollPrev(),
|
|
173
|
-
canScrollNext: () => emblaApi.canScrollNext(),
|
|
174
|
-
destroy: () => {
|
|
175
|
-
// Remove event listeners to prevent memory leaks
|
|
176
|
-
if (prevButtonEl) {
|
|
177
|
-
prevButtonEl.removeEventListener("click", prevClickHandler)
|
|
178
|
-
}
|
|
179
|
-
if (nextButtonEl) {
|
|
180
|
-
nextButtonEl.removeEventListener("click", nextClickHandler)
|
|
181
|
-
}
|
|
182
|
-
carouselElement.removeEventListener("keydown", keydownHandler)
|
|
183
|
-
|
|
184
|
-
// Destroy the Embla instance
|
|
185
|
-
emblaApi.destroy()
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
1
|
+
import EmblaCarousel, {
|
|
2
|
+
type EmblaCarouselType,
|
|
3
|
+
type EmblaOptionsType,
|
|
4
|
+
type EmblaPluginType
|
|
5
|
+
} from "embla-carousel"
|
|
6
|
+
|
|
7
|
+
export type CarouselApi = EmblaCarouselType
|
|
8
|
+
|
|
9
|
+
export interface CarouselOptions {
|
|
10
|
+
opts?: EmblaOptionsType
|
|
11
|
+
plugins?: EmblaPluginType[]
|
|
12
|
+
setApi?: (api: CarouselApi) => void
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface CarouselManager {
|
|
16
|
+
api: CarouselApi
|
|
17
|
+
scrollPrev: () => void
|
|
18
|
+
scrollNext: () => void
|
|
19
|
+
canScrollPrev: () => boolean
|
|
20
|
+
canScrollNext: () => boolean
|
|
21
|
+
destroy: () => void
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function initCarousel(
|
|
25
|
+
carouselElement: HTMLElement,
|
|
26
|
+
options: CarouselOptions = {}
|
|
27
|
+
): CarouselManager | null {
|
|
28
|
+
// don't re-initialize if already initialized
|
|
29
|
+
if (carouselElement.dataset.initialized === "true") return null
|
|
30
|
+
carouselElement.dataset.initialized = "true"
|
|
31
|
+
|
|
32
|
+
if (!carouselElement) {
|
|
33
|
+
console.warn("Carousel element not found")
|
|
34
|
+
return null
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Find content element - Embla expects the viewport element, not the container
|
|
38
|
+
const viewportElement = carouselElement.querySelector('[data-slot="carousel-content"]')
|
|
39
|
+
|
|
40
|
+
if (!(viewportElement instanceof HTMLElement)) {
|
|
41
|
+
console.warn("Carousel content element not found")
|
|
42
|
+
return null
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Get configuration from data attributes
|
|
46
|
+
const axisData = carouselElement.dataset.axis
|
|
47
|
+
const axis: EmblaOptionsType["axis"] = axisData === "y" ? "y" : "x"
|
|
48
|
+
|
|
49
|
+
// Safely parse data options
|
|
50
|
+
let dataOpts = {}
|
|
51
|
+
try {
|
|
52
|
+
const optsString = carouselElement.dataset.opts
|
|
53
|
+
if (optsString && optsString !== "undefined" && optsString !== "null") {
|
|
54
|
+
dataOpts = JSON.parse(optsString)
|
|
55
|
+
}
|
|
56
|
+
} catch (e) {
|
|
57
|
+
console.warn("Failed to parse carousel opts:", e)
|
|
58
|
+
dataOpts = {}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Ensure dataOpts is a valid object
|
|
62
|
+
if (!dataOpts || typeof dataOpts !== "object") {
|
|
63
|
+
dataOpts = {}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Merge options - ensure we always have a valid object
|
|
67
|
+
const emblaOptions: EmblaOptionsType = {
|
|
68
|
+
axis,
|
|
69
|
+
...dataOpts,
|
|
70
|
+
...options.opts
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Handle plugins - EmblaCarousel expects undefined when no plugins, not empty array
|
|
74
|
+
const plugins = options.plugins && options.plugins.length > 0 ? options.plugins : undefined
|
|
75
|
+
|
|
76
|
+
// console.log("ID:", carouselElement.id);
|
|
77
|
+
// console.log("Plugins:", plugins);
|
|
78
|
+
// console.log("Options:", emblaOptions);
|
|
79
|
+
|
|
80
|
+
// Find navigation buttons
|
|
81
|
+
const prevButton = carouselElement.querySelector(".starwind-carousel-previous")
|
|
82
|
+
const nextButton = carouselElement.querySelector(".starwind-carousel-next")
|
|
83
|
+
|
|
84
|
+
const prevButtonEl = prevButton instanceof HTMLButtonElement ? prevButton : null
|
|
85
|
+
const nextButtonEl = nextButton instanceof HTMLButtonElement ? nextButton : null
|
|
86
|
+
|
|
87
|
+
// Initialize Embla
|
|
88
|
+
let emblaApi: EmblaCarouselType
|
|
89
|
+
if (plugins) {
|
|
90
|
+
emblaApi = EmblaCarousel(viewportElement, emblaOptions, plugins)
|
|
91
|
+
} else {
|
|
92
|
+
emblaApi = EmblaCarousel(viewportElement, emblaOptions)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Update button states
|
|
96
|
+
const updateButtons = () => {
|
|
97
|
+
const canScrollPrev = emblaApi.canScrollPrev()
|
|
98
|
+
const canScrollNext = emblaApi.canScrollNext()
|
|
99
|
+
|
|
100
|
+
if (prevButtonEl) {
|
|
101
|
+
prevButtonEl.disabled = !canScrollPrev
|
|
102
|
+
prevButtonEl.setAttribute("aria-disabled", (!canScrollPrev).toString())
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (nextButtonEl) {
|
|
106
|
+
nextButtonEl.disabled = !canScrollNext
|
|
107
|
+
nextButtonEl.setAttribute("aria-disabled", (!canScrollNext).toString())
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Event handlers for cleanup
|
|
112
|
+
const prevClickHandler = () => emblaApi.scrollPrev()
|
|
113
|
+
const nextClickHandler = () => emblaApi.scrollNext()
|
|
114
|
+
const keydownHandler = (event: KeyboardEvent) => {
|
|
115
|
+
if (axis === "y") {
|
|
116
|
+
// Vertical axis: ArrowUp = previous, ArrowDown = next
|
|
117
|
+
if (event.key === "ArrowUp") {
|
|
118
|
+
event.preventDefault()
|
|
119
|
+
emblaApi.scrollPrev()
|
|
120
|
+
} else if (event.key === "ArrowDown") {
|
|
121
|
+
event.preventDefault()
|
|
122
|
+
emblaApi.scrollNext()
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
// Horizontal axis (default): ArrowLeft = previous, ArrowRight = next
|
|
126
|
+
if (event.key === "ArrowLeft") {
|
|
127
|
+
event.preventDefault()
|
|
128
|
+
emblaApi.scrollPrev()
|
|
129
|
+
} else if (event.key === "ArrowRight") {
|
|
130
|
+
event.preventDefault()
|
|
131
|
+
emblaApi.scrollNext()
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Setup event listeners
|
|
137
|
+
const setupEventListeners = () => {
|
|
138
|
+
// Navigation button listeners
|
|
139
|
+
prevButtonEl?.addEventListener("click", prevClickHandler)
|
|
140
|
+
nextButtonEl?.addEventListener("click", nextClickHandler)
|
|
141
|
+
|
|
142
|
+
// Keyboard navigation
|
|
143
|
+
carouselElement.addEventListener("keydown", keydownHandler)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Setup user API callback
|
|
147
|
+
const setupUserCallbacks = () => {
|
|
148
|
+
if (options.setApi) {
|
|
149
|
+
options.setApi(emblaApi)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Initialize everything
|
|
154
|
+
updateButtons()
|
|
155
|
+
setupEventListeners()
|
|
156
|
+
setupUserCallbacks()
|
|
157
|
+
|
|
158
|
+
// Setup internal event listeners
|
|
159
|
+
emblaApi.on("select", updateButtons)
|
|
160
|
+
emblaApi.on("init", () => {
|
|
161
|
+
updateButtons()
|
|
162
|
+
})
|
|
163
|
+
emblaApi.on("reInit", () => {
|
|
164
|
+
updateButtons()
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
// Return manager interface
|
|
168
|
+
return {
|
|
169
|
+
api: emblaApi,
|
|
170
|
+
scrollPrev: () => emblaApi.scrollPrev(),
|
|
171
|
+
scrollNext: () => emblaApi.scrollNext(),
|
|
172
|
+
canScrollPrev: () => emblaApi.canScrollPrev(),
|
|
173
|
+
canScrollNext: () => emblaApi.canScrollNext(),
|
|
174
|
+
destroy: () => {
|
|
175
|
+
// Remove event listeners to prevent memory leaks
|
|
176
|
+
if (prevButtonEl) {
|
|
177
|
+
prevButtonEl.removeEventListener("click", prevClickHandler)
|
|
178
|
+
}
|
|
179
|
+
if (nextButtonEl) {
|
|
180
|
+
nextButtonEl.removeEventListener("click", nextClickHandler)
|
|
181
|
+
}
|
|
182
|
+
carouselElement.removeEventListener("keydown", keydownHandler)
|
|
183
|
+
|
|
184
|
+
// Destroy the Embla instance
|
|
185
|
+
emblaApi.destroy()
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from "./carousel-script"
|
|
1
|
+
export * from "./carousel-script"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export interface InputOtpChangeEvent extends CustomEvent {
|
|
2
|
-
detail: {
|
|
3
|
-
value: string
|
|
4
|
-
inputOtpId?: string
|
|
5
|
-
}
|
|
6
|
-
}
|
|
1
|
+
export interface InputOtpChangeEvent extends CustomEvent {
|
|
2
|
+
detail: {
|
|
3
|
+
value: string
|
|
4
|
+
inputOtpId?: string
|
|
5
|
+
}
|
|
6
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export interface RadioGroupChangeEvent extends CustomEvent {
|
|
2
|
-
detail: {
|
|
3
|
-
value: string
|
|
4
|
-
radioGroupId?: string
|
|
5
|
-
}
|
|
6
|
-
}
|
|
1
|
+
export interface RadioGroupChangeEvent extends CustomEvent {
|
|
2
|
+
detail: {
|
|
3
|
+
value: string
|
|
4
|
+
radioGroupId?: string
|
|
5
|
+
}
|
|
6
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export interface SelectChangeEvent extends CustomEvent {
|
|
2
|
-
detail: {
|
|
3
|
-
value: string
|
|
4
|
-
selectId: string
|
|
5
|
-
label: string
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export interface SelectEvent extends CustomEvent {
|
|
10
|
-
detail:
|
|
11
|
-
| { value: string; selectId: string; selectName?: string }
|
|
12
|
-
| { value: string; selectId?: string; selectName: string }
|
|
13
|
-
}
|
|
1
|
+
export interface SelectChangeEvent extends CustomEvent {
|
|
2
|
+
detail: {
|
|
3
|
+
value: string
|
|
4
|
+
selectId: string
|
|
5
|
+
label: string
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface SelectEvent extends CustomEvent {
|
|
10
|
+
detail:
|
|
11
|
+
| { value: string; selectId: string; selectName?: string }
|
|
12
|
+
| { value: string; selectId?: string; selectName: string }
|
|
13
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export interface SwitchChangeEvent extends CustomEvent {
|
|
2
|
-
detail: {
|
|
3
|
-
checked: boolean
|
|
4
|
-
switchId: string
|
|
5
|
-
}
|
|
6
|
-
}
|
|
1
|
+
export interface SwitchChangeEvent extends CustomEvent {
|
|
2
|
+
detail: {
|
|
3
|
+
checked: boolean
|
|
4
|
+
switchId: string
|
|
5
|
+
}
|
|
6
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from "./toast-manager"
|
|
1
|
+
export * from "./toast-manager"
|