solid-tom-ui 1.0.11 → 1.0.15
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 +246 -246
- package/dist/README.md +246 -246
- package/dist/components/avatar/avatar.js.map +1 -1
- package/dist/components/badge/badge.js.map +1 -1
- package/dist/components/breadcrumb/breadcrumb.js.map +1 -1
- package/dist/components/button/button.js.map +1 -1
- package/dist/components/carousel/carousel.js.map +1 -1
- package/dist/components/chat-bubble/chatBubble.js.map +1 -1
- package/dist/components/checkbox/checkbox.js.map +1 -1
- package/dist/components/collapse/collapse.js.map +1 -1
- package/dist/components/context-menu/context-menu.js.map +1 -1
- package/dist/components/context-menu/context-menu.store.js.map +1 -1
- package/dist/components/divider/divider.js.map +1 -1
- package/dist/components/dropdown/dropdown.js.map +1 -1
- package/dist/components/dropdown/dropdown.store.js.map +1 -1
- package/dist/components/float-button/float-button.js.map +1 -1
- package/dist/components/hover-3d-image/hover-3d-image.js.map +1 -1
- package/dist/components/image-preview/image-preview.js.map +1 -1
- package/dist/components/input/input.js.map +1 -1
- package/dist/components/input/input.utils.js.map +1 -1
- package/dist/components/input/variants/input-color.js.map +1 -1
- package/dist/components/input/variants/input-date.js.map +1 -1
- package/dist/components/input/variants/input-number.d.ts.map +1 -1
- package/dist/components/input/variants/input-number.js +1 -1
- package/dist/components/input/variants/input-number.js.map +1 -1
- package/dist/components/input/variants/input-otp.js.map +1 -1
- package/dist/components/input/variants/input-password.js.map +1 -1
- package/dist/components/input/variants/input-radio.js.map +1 -1
- package/dist/components/input/variants/input-range.js.map +1 -1
- package/dist/components/input/variants/input-text.d.ts.map +1 -1
- package/dist/components/input/variants/input-text.js +1 -1
- package/dist/components/input/variants/input-text.js.map +1 -1
- package/dist/components/input/variants/input-textarea.js.map +1 -1
- package/dist/components/loading/loading.js.map +1 -1
- package/dist/components/mansory/mansory.js.map +1 -1
- package/dist/components/menu/menu.js.map +1 -1
- package/dist/components/modal/modal.js.map +1 -1
- package/dist/components/modal/modalContext.js.map +1 -1
- package/dist/components/pagination/pagination.js.map +1 -1
- package/dist/components/progress-bar/progress-bar.js.map +1 -1
- package/dist/components/qr-code/qr-code.js.map +1 -1
- package/dist/components/select/select.js +1 -1
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/select-zone/select-zone.js.map +1 -1
- package/dist/components/skeleton/skeleton.js.map +1 -1
- package/dist/components/slider/slider.js.map +1 -1
- package/dist/components/splitter/splitter.js.map +1 -1
- package/dist/components/steps/steps.js.map +1 -1
- package/dist/components/swap/swap.js.map +1 -1
- package/dist/components/switch/switch.js.map +1 -1
- package/dist/components/tab/tab.js.map +1 -1
- package/dist/components/table/table.js.map +1 -1
- package/dist/components/timeline/timeline.js.map +1 -1
- package/dist/components/toast/icons/ErrorIcon.js.map +1 -1
- package/dist/components/toast/icons/IconCircle.js.map +1 -1
- package/dist/components/toast/icons/InfoIcon.js.map +1 -1
- package/dist/components/toast/icons/LoaderIcon.js.map +1 -1
- package/dist/components/toast/icons/SuccessIcon.js.map +1 -1
- package/dist/components/toast/icons/WarningIcon.js.map +1 -1
- package/dist/components/toast/toast.js.map +1 -1
- package/dist/components/toast/toast.store.js.map +1 -1
- package/dist/components/tooltip/tooltip.js.map +1 -1
- package/dist/components/tour/tour.js.map +1 -1
- package/dist/components/upload/upload.js.map +1 -1
- package/dist/components/z-index/z-index.context.js.map +1 -1
- package/dist/components/z-index/z-index.js.map +1 -1
- package/dist/components/z-index/z-index.store.js.map +1 -1
- package/dist/components/z-index/z-index.types.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/skill/avatar.skill.md.txt +255 -255
- package/dist/skill/badge.skill.md.txt +223 -223
- package/dist/skill/breadcrumb.skill.md.txt +177 -177
- package/dist/skill/button.skill.md.txt +198 -198
- package/dist/skill/carousel.skill.md.txt +406 -406
- package/dist/skill/chat-bubble.skill.md.txt +342 -342
- package/dist/skill/checkbox.skill.md.txt +326 -326
- package/dist/skill/code-preview.skill.md.txt +240 -240
- package/dist/skill/collapse.skill.md.txt +329 -329
- package/dist/skill/context-menu.skill.md.txt +233 -233
- package/dist/skill/diff.skill.md.txt +244 -244
- package/dist/skill/divider.skill.md.txt +151 -151
- package/dist/skill/doc.skill.md.txt +191 -191
- package/dist/skill/drawer.skill.md.txt +157 -157
- package/dist/skill/dropdown.skill.md.txt +198 -198
- package/dist/skill/float-button.skill.md.txt +315 -315
- package/dist/skill/hover-3d-image.skill.md.txt +120 -120
- package/dist/skill/iframe.skill.md.txt +114 -114
- package/dist/skill/image-preview.skill.md.txt +162 -162
- package/dist/skill/indicator.skill.md.txt +60 -60
- package/dist/skill/input.skill.md.txt +489 -489
- package/dist/skill/loading.skill.md.txt +127 -127
- package/dist/skill/menu.skill.md.txt +476 -476
- package/dist/skill/modal.skill.md.txt +359 -359
- package/dist/skill/pagination.skill.md.txt +405 -405
- package/dist/skill/progress-bar.skill.md.txt +207 -207
- package/dist/skill/qr-code.skill.md.txt +136 -136
- package/dist/skill/rating.skill.md.txt +167 -167
- package/dist/skill/select-zone.skill.md.txt +93 -93
- package/dist/skill/select.skill.md.txt +663 -663
- package/dist/skill/skeleton.skill.md.txt +192 -192
- package/dist/skill/slider.skill.md.txt +404 -404
- package/dist/skill/splitter.skill.md.txt +411 -411
- package/dist/skill/steps.skill.md.txt +264 -264
- package/dist/skill/swap.skill.md.txt +139 -139
- package/dist/skill/switch.skill.md.txt +191 -191
- package/dist/skill/tab.skill.md.txt +484 -484
- package/dist/skill/table.example.header.md.txt +666 -666
- package/dist/skill/table.skill.md.txt +1407 -1407
- package/dist/skill/text-rotate.skill.md.txt +186 -186
- package/dist/skill/timeline.skill.md.txt +247 -247
- package/dist/skill/toast.skill.md.txt +531 -531
- package/dist/skill/tooltip.skill.md.txt +222 -222
- package/dist/skill/tour.skill.md.txt +156 -156
- package/dist/skill/upload.skill.md.txt +358 -358
- package/dist/utils/cn.js.map +1 -1
- package/dist/utils/element-tracker.js.map +1 -1
- package/dist/utils/helper.js.map +1 -1
- package/dist/utils/hoc.js.map +1 -1
- package/package.json +132 -133
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loading.js","names":["cn","BaseColorProps","cva","VariantProps","Component","createUniqueId","mergeProps","Switch","Match","Loader","daisy_variants","variants","variant","spinner","dots","ring","ball","bars","infinity","size","xs","sm","md","lg","xl","svg_size_map","const","base_color_vars","Record","primary","secondary","accent","neutral","info","success","warning","error","resolveColor","color","undefined","DaisyVariant","SvgVariant","SizeKey","LoadingProps","class","LoadingVariantsProps","Loading","props","p","isDaisy","includes","resolvedColor","svgClass","_$createComponent","children","when","_el$","_tmpl$","_$effect","_p$","_v$","_v$2","e","_$className","t","_$style","LoadingSpinner3","LoadingSpinner4","LoadingSpinner5","LoadingSpinner6","Spinner","id","_el$2","_tmpl$2","_el$3","firstChild","_el$4","_el$5","nextSibling","_el$6","_el$7","_el$8","_el$9","_el$0","_$setAttribute","_v$3","_v$4","_v$5","_v$6","_v$7","a","o","i","_el$1","_tmpl$3","_v$8","_v$9","_$setStyleProperty","_el$10","_tmpl$4","_v$0","_v$1","_el$11","_tmpl$5","_el$12","_el$13","_el$14","_v$10","_v$11"],"sources":["../../../src/components/loading/loading.tsx"],"sourcesContent":["import { cn } from '@/utils/cn';\nimport { BaseColorProps } from '@/type';\nimport { cva, VariantProps } from 'class-variance-authority';\nimport { Component, createUniqueId, mergeProps, Switch, Match } from 'solid-js';\nimport Loader from 'lucide-solid/icons/loader';\n\n// Variants dùng DaisyUI classes (spinner, spinner-2, dots, ring, ball, bars, infinity)\nconst daisy_variants = cva('loading', {\n variants: {\n variant: {\n spinner: 'loading-spinner',\n 'spinner-2': 'loading-spinner-2',\n dots: 'loading-dots',\n ring: 'loading-ring',\n ball: 'loading-ball',\n bars: 'loading-bars',\n infinity: 'loading-infinity',\n },\n size: {\n xs: 'loading-xs',\n sm: 'loading-sm',\n md: 'loading-md',\n lg: 'loading-lg',\n xl: 'loading-xl',\n },\n },\n});\n\n// Map size → CSS class cho SVG-based spinners\nconst svg_size_map = {\n xs: 'loading-svg-xs',\n sm: 'loading-svg-sm',\n md: 'loading-svg-md',\n lg: 'loading-svg-lg',\n xl: 'loading-svg-xl',\n} as const;\n\n// Map BaseColorProps → CSS variable của DaisyUI/Tailwind\nconst base_color_vars: Record<BaseColorProps, string> = {\n primary: 'var(--color-primary)',\n secondary: 'var(--color-secondary)',\n accent: 'var(--color-accent)',\n neutral: 'var(--color-neutral)',\n info: 'var(--color-info)',\n success: 'var(--color-success)',\n warning: 'var(--color-warning)',\n error: 'var(--color-error)',\n};\n\n/** Resolve color prop: nếu là BaseColorProps key thì map sang CSS var, còn lại dùng trực tiếp */\nfunction resolveColor(color: string | undefined): string | undefined {\n if (!color) return undefined;\n return color in base_color_vars ? base_color_vars[color as BaseColorProps] : color;\n}\n\ntype DaisyVariant = 'spinner' | 'spinner-2' | 'dots' | 'ring' | 'ball' | 'bars' | 'infinity';\ntype SvgVariant = 'spinner-3' | 'spinner-4' | 'spinner-5' | 'spinner-6';\ntype SizeKey = keyof typeof svg_size_map;\n\ntype LoadingProps = {\n variant?: DaisyVariant | SvgVariant;\n size?: SizeKey;\n /** Nhận BaseColorProps ('primary', 'error', ...) hoặc bất kỳ giá trị CSS color nào */\n color?: BaseColorProps | string;\n class?: string;\n};\n\nexport type LoadingVariantsProps = VariantProps<typeof daisy_variants>;\n\nexport const Loading: Component<LoadingProps> = props => {\n const p = mergeProps({ variant: 'spinner' as const, size: 'sm' as const }, props);\n\n const isDaisy = () =>\n !['spinner-3', 'spinner-4', 'spinner-5', 'spinner-6'].includes(p.variant as string);\n\n const resolvedColor = () => resolveColor(p.color);\n const svgClass = () => cn(svg_size_map[p.size as SizeKey], p.class);\n\n return (\n <Switch>\n <Match when={isDaisy()}>\n <div\n class={cn(\n daisy_variants({\n variant: p.variant as DaisyVariant,\n size: p.size,\n }),\n p.class,\n )}\n style={resolvedColor() ? { color: resolvedColor() } : undefined}\n />\n </Match>\n <Match when={p.variant === 'spinner-3'}>\n <LoadingSpinner3 class={svgClass()} color={resolvedColor()} />\n </Match>\n <Match when={p.variant === 'spinner-4'}>\n <LoadingSpinner4 class={svgClass()} color={resolvedColor()} />\n </Match>\n <Match when={p.variant === 'spinner-5'}>\n <LoadingSpinner5 class={svgClass()} color={resolvedColor()} />\n </Match>\n <Match when={p.variant === 'spinner-6'}>\n <LoadingSpinner6 class={svgClass()} color={resolvedColor()} />\n </Match>\n </Switch>\n );\n};\nexport const Spinner: Component<{ class?: string; color?: string }> = p => {\n const id = createUniqueId();\n\n p = mergeProps({ color: '#6E56CF' } as const, p);\n\n return (\n <div class={cn('size-3 animate-spin', p.class)}>\n <svg\n width=\"inherit\"\n height=\"inherit\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <ellipse\n cx=\"9.99995\"\n cy=\"9.99995\"\n rx=\"7.31001\"\n ry=\"7.31001\"\n stroke={p.color}\n stroke-opacity=\"0.25\"\n stroke-width=\"4\"\n />\n <path\n d=\"M9.94939 2.69013C11.8881 2.67671 13.7527 3.43398 15.133 4.79535C16.5134 6.15671 17.2964 8.01067 17.3098 9.94936\"\n stroke={`url(#${id})`}\n stroke-width=\"4\"\n stroke-linecap=\"round\"\n stroke-dasharray=\"1.23 1.23\"\n />\n <defs>\n <linearGradient\n id={id}\n x1=\"16.3108\"\n y1=\"13.6892\"\n x2=\"3.68922\"\n y2=\"6.31075\"\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop stop-color={p.color} />\n <stop offset=\"0.5\" stop-color={p.color} stop-opacity=\"0.01\" />\n <stop offset=\"1\" stop-color={p.color} stop-opacity=\"0\" />\n </linearGradient>\n </defs>\n </svg>\n </div>\n );\n};\nconst LoadingSpinner3: Component<{ class?: string; color?: string }> = p => {\n p = mergeProps({ color: 'currentColor' } as const, p);\n return (\n <div class={cn('size-7 p-0', p.class)} style={{ color: p.color }}>\n <svg fill=\"currentColor\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <g>\n <circle cx=\"12\" cy=\"3\" r=\"1\">\n <animate\n id=\"_dcbb18\"\n begin=\"0;_84a13e.end-0.5s\"\n attributeName=\"r\"\n calcMode=\"spline\"\n dur=\"0.6s\"\n values=\"1;2;1\"\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\n />\n </circle>\n <circle cx=\"16.50\" cy=\"4.21\" r=\"1\">\n <animate\n id=\"_92c238\"\n begin=\"_dcbb18.begin+0.1s\"\n attributeName=\"r\"\n calcMode=\"spline\"\n dur=\"0.6s\"\n values=\"1;2;1\"\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\n />\n </circle>\n <circle cx=\"7.50\" cy=\"4.21\" r=\"1\">\n <animate\n id=\"_84a13e\"\n begin=\"_5abc3e.begin+0.1s\"\n attributeName=\"r\"\n calcMode=\"spline\"\n dur=\"0.6s\"\n values=\"1;2;1\"\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\n />\n </circle>\n <circle cx=\"19.79\" cy=\"7.50\" r=\"1\">\n <animate\n id=\"_9d19c8\"\n begin=\"_92c238.begin+0.1s\"\n attributeName=\"r\"\n calcMode=\"spline\"\n dur=\"0.6s\"\n values=\"1;2;1\"\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\n />\n </circle>\n <circle cx=\"4.21\" cy=\"7.50\" r=\"1\">\n <animate\n id=\"_5abc3e\"\n begin=\"_dcfbb2.begin+0.1s\"\n attributeName=\"r\"\n calcMode=\"spline\"\n dur=\"0.6s\"\n values=\"1;2;1\"\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\n />\n </circle>\n <circle cx=\"21.00\" cy=\"12.00\" r=\"1\">\n <animate\n id=\"_cf88a3\"\n begin=\"_9d19c8.begin+0.1s\"\n attributeName=\"r\"\n calcMode=\"spline\"\n dur=\"0.6s\"\n values=\"1;2;1\"\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\n />\n </circle>\n <circle cx=\"3.00\" cy=\"12.00\" r=\"1\">\n <animate\n id=\"_dcfbb2\"\n begin=\"_514e98.begin+0.1s\"\n attributeName=\"r\"\n calcMode=\"spline\"\n dur=\"0.6s\"\n values=\"1;2;1\"\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\n />\n </circle>\n <circle cx=\"19.79\" cy=\"16.50\" r=\"1\">\n <animate\n id=\"_2fecf8\"\n begin=\"_cf88a3.begin+0.1s\"\n attributeName=\"r\"\n calcMode=\"spline\"\n dur=\"0.6s\"\n values=\"1;2;1\"\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\n />\n </circle>\n <circle cx=\"4.21\" cy=\"16.50\" r=\"1\">\n <animate\n id=\"_514e98\"\n begin=\"_c4d048.begin+0.1s\"\n attributeName=\"r\"\n calcMode=\"spline\"\n dur=\"0.6s\"\n values=\"1;2;1\"\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\n />\n </circle>\n <circle cx=\"16.50\" cy=\"19.79\" r=\"1\">\n <animate\n id=\"_033759\"\n begin=\"_2fecf8.begin+0.1s\"\n attributeName=\"r\"\n calcMode=\"spline\"\n dur=\"0.6s\"\n values=\"1;2;1\"\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\n />\n </circle>\n <circle cx=\"7.50\" cy=\"19.79\" r=\"1\">\n <animate\n id=\"_c4d048\"\n begin=\"_3ec8bd.begin+0.1s\"\n attributeName=\"r\"\n calcMode=\"spline\"\n dur=\"0.6s\"\n values=\"1;2;1\"\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\n />\n </circle>\n <circle cx=\"12\" cy=\"21\" r=\"1\">\n <animate\n id=\"_3ec8bd\"\n begin=\"_033759.begin+0.1s\"\n attributeName=\"r\"\n calcMode=\"spline\"\n dur=\"0.6s\"\n values=\"1;2;1\"\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\n />\n </circle>\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n dur=\"6s\"\n values=\"360 12 12;0 12 12\"\n repeatCount=\"indefinite\"\n />\n </g>\n </svg>\n </div>\n );\n};\nconst LoadingSpinner4: Component<{ class?: string; color?: string }> = p => {\n return <Loader class={cn('animate-spin', p.class)} color={p.color} />;\n};\nconst LoadingSpinner5: Component<{ class?: string; color?: string }> = p => {\n p = mergeProps({ class: 'size-6' } as const, p);\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n x=\"0px\"\n y=\"0px\"\n viewBox=\"0 0 2400 2400\"\n class={p.class}\n style={{ color: p.color }}\n >\n <g stroke-width=\"200\" stroke-linecap=\"round\" stroke=\"currentColor\" fill=\"none\" id=\"spinner\">\n <line x1=\"1200\" y1=\"600\" x2=\"1200\" y2=\"100\" />\n <line opacity=\"0.5\" x1=\"1200\" y1=\"2300\" x2=\"1200\" y2=\"1800\" />\n <line opacity=\"0.917\" x1=\"900\" y1=\"680.4\" x2=\"650\" y2=\"247.4\" />\n <line opacity=\"0.417\" x1=\"1750\" y1=\"2152.6\" x2=\"1500\" y2=\"1719.6\" />\n <line opacity=\"0.833\" x1=\"680.4\" y1=\"900\" x2=\"247.4\" y2=\"650\" />\n <line opacity=\"0.333\" x1=\"2152.6\" y1=\"1750\" x2=\"1719.6\" y2=\"1500\" />\n <line opacity=\"0.75\" x1=\"600\" y1=\"1200\" x2=\"100\" y2=\"1200\" />\n <line opacity=\"0.25\" x1=\"2300\" y1=\"1200\" x2=\"1800\" y2=\"1200\" />\n <line opacity=\"0.667\" x1=\"680.4\" y1=\"1500\" x2=\"247.4\" y2=\"1750\" />\n <line opacity=\"0.167\" x1=\"2152.6\" y1=\"650\" x2=\"1719.6\" y2=\"900\" />\n <line opacity=\"0.583\" x1=\"900\" y1=\"1719.6\" x2=\"650\" y2=\"2152.6\" />\n <line opacity=\"0.083\" x1=\"1750\" y1=\"247.4\" x2=\"1500\" y2=\"680.4\" />\n <animateTransform\n attributeName=\"transform\"\n attributeType=\"XML\"\n type=\"rotate\"\n keyTimes=\"0;0.08333;0.16667;0.25;0.33333;0.41667;0.5;0.58333;0.66667;0.75;0.83333;0.91667\"\n values=\"0 1199 1199;30 1199 1199;60 1199 1199;90 1199 1199;120 1199 1199;150 1199 1199;180 1199 1199;210 1199 1199;240 1199 1199;270 1199 1199;300 1199 1199;330 1199 1199\"\n dur=\"0.83333s\"\n begin=\"0s\"\n repeatCount=\"indefinite\"\n calcMode=\"discrete\"\n />\n </g>\n </svg>\n );\n};\nconst LoadingSpinner6: Component<{ class?: string; color?: string }> = p => {\n p = mergeProps({ class: 'size-6' } as const, p);\n const id = createUniqueId();\n return (\n <svg\n fill=\"none\"\n viewBox=\"0 0 20 20\"\n xmlns=\"http://www.w3.org/2000/svg\"\n class={p.class}\n style={{ color: p.color }}\n >\n <defs>\n <linearGradient id={id}>\n <stop offset=\"0%\" stop-color=\"currentColor\" stop-opacity=\"1\" />\n <stop offset=\"100%\" stop-color=\"currentColor\" stop-opacity=\"0.25\" />\n </linearGradient>\n </defs>\n <circle\n cx=\"10\"\n cy=\"10\"\n r=\"8\"\n stroke-width=\"2\"\n class=\"animate-spin\"\n stroke={`url(#${id})`}\n fill=\"none\"\n style={{ 'transform-origin': '50% 50%' }}\n />\n </svg>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"loading.js","names":["cn","BaseColorProps","cva","VariantProps","Component","createUniqueId","mergeProps","Switch","Match","Loader","daisy_variants","variants","variant","spinner","dots","ring","ball","bars","infinity","size","xs","sm","md","lg","xl","svg_size_map","const","base_color_vars","Record","primary","secondary","accent","neutral","info","success","warning","error","resolveColor","color","undefined","DaisyVariant","SvgVariant","SizeKey","LoadingProps","class","LoadingVariantsProps","Loading","props","p","isDaisy","includes","resolvedColor","svgClass","_$createComponent","children","when","_el$","_tmpl$","_$effect","_p$","_v$","_v$2","e","_$className","t","_$style","LoadingSpinner3","LoadingSpinner4","LoadingSpinner5","LoadingSpinner6","Spinner","id","_el$2","_tmpl$2","_el$3","firstChild","_el$4","_el$5","nextSibling","_el$6","_el$7","_el$8","_el$9","_el$0","_$setAttribute","_v$3","_v$4","_v$5","_v$6","_v$7","a","o","i","_el$1","_tmpl$3","_v$8","_v$9","_$setStyleProperty","_el$10","_tmpl$4","_v$0","_v$1","_el$11","_tmpl$5","_el$12","_el$13","_el$14","_v$10","_v$11"],"sources":["../../../src/components/loading/loading.tsx"],"sourcesContent":["import { cn } from '@/utils/cn';\r\nimport { BaseColorProps } from '@/type';\r\nimport { cva, VariantProps } from 'class-variance-authority';\r\nimport { Component, createUniqueId, mergeProps, Switch, Match } from 'solid-js';\r\nimport Loader from 'lucide-solid/icons/loader';\r\n\r\n// Variants dùng DaisyUI classes (spinner, spinner-2, dots, ring, ball, bars, infinity)\r\nconst daisy_variants = cva('loading', {\r\n variants: {\r\n variant: {\r\n spinner: 'loading-spinner',\r\n 'spinner-2': 'loading-spinner-2',\r\n dots: 'loading-dots',\r\n ring: 'loading-ring',\r\n ball: 'loading-ball',\r\n bars: 'loading-bars',\r\n infinity: 'loading-infinity',\r\n },\r\n size: {\r\n xs: 'loading-xs',\r\n sm: 'loading-sm',\r\n md: 'loading-md',\r\n lg: 'loading-lg',\r\n xl: 'loading-xl',\r\n },\r\n },\r\n});\r\n\r\n// Map size → CSS class cho SVG-based spinners\r\nconst svg_size_map = {\r\n xs: 'loading-svg-xs',\r\n sm: 'loading-svg-sm',\r\n md: 'loading-svg-md',\r\n lg: 'loading-svg-lg',\r\n xl: 'loading-svg-xl',\r\n} as const;\r\n\r\n// Map BaseColorProps → CSS variable của DaisyUI/Tailwind\r\nconst base_color_vars: Record<BaseColorProps, string> = {\r\n primary: 'var(--color-primary)',\r\n secondary: 'var(--color-secondary)',\r\n accent: 'var(--color-accent)',\r\n neutral: 'var(--color-neutral)',\r\n info: 'var(--color-info)',\r\n success: 'var(--color-success)',\r\n warning: 'var(--color-warning)',\r\n error: 'var(--color-error)',\r\n};\r\n\r\n/** Resolve color prop: nếu là BaseColorProps key thì map sang CSS var, còn lại dùng trực tiếp */\r\nfunction resolveColor(color: string | undefined): string | undefined {\r\n if (!color) return undefined;\r\n return color in base_color_vars ? base_color_vars[color as BaseColorProps] : color;\r\n}\r\n\r\ntype DaisyVariant = 'spinner' | 'spinner-2' | 'dots' | 'ring' | 'ball' | 'bars' | 'infinity';\r\ntype SvgVariant = 'spinner-3' | 'spinner-4' | 'spinner-5' | 'spinner-6';\r\ntype SizeKey = keyof typeof svg_size_map;\r\n\r\ntype LoadingProps = {\r\n variant?: DaisyVariant | SvgVariant;\r\n size?: SizeKey;\r\n /** Nhận BaseColorProps ('primary', 'error', ...) hoặc bất kỳ giá trị CSS color nào */\r\n color?: BaseColorProps | string;\r\n class?: string;\r\n};\r\n\r\nexport type LoadingVariantsProps = VariantProps<typeof daisy_variants>;\r\n\r\nexport const Loading: Component<LoadingProps> = props => {\r\n const p = mergeProps({ variant: 'spinner' as const, size: 'sm' as const }, props);\r\n\r\n const isDaisy = () =>\r\n !['spinner-3', 'spinner-4', 'spinner-5', 'spinner-6'].includes(p.variant as string);\r\n\r\n const resolvedColor = () => resolveColor(p.color);\r\n const svgClass = () => cn(svg_size_map[p.size as SizeKey], p.class);\r\n\r\n return (\r\n <Switch>\r\n <Match when={isDaisy()}>\r\n <div\r\n class={cn(\r\n daisy_variants({\r\n variant: p.variant as DaisyVariant,\r\n size: p.size,\r\n }),\r\n p.class,\r\n )}\r\n style={resolvedColor() ? { color: resolvedColor() } : undefined}\r\n />\r\n </Match>\r\n <Match when={p.variant === 'spinner-3'}>\r\n <LoadingSpinner3 class={svgClass()} color={resolvedColor()} />\r\n </Match>\r\n <Match when={p.variant === 'spinner-4'}>\r\n <LoadingSpinner4 class={svgClass()} color={resolvedColor()} />\r\n </Match>\r\n <Match when={p.variant === 'spinner-5'}>\r\n <LoadingSpinner5 class={svgClass()} color={resolvedColor()} />\r\n </Match>\r\n <Match when={p.variant === 'spinner-6'}>\r\n <LoadingSpinner6 class={svgClass()} color={resolvedColor()} />\r\n </Match>\r\n </Switch>\r\n );\r\n};\r\nexport const Spinner: Component<{ class?: string; color?: string }> = p => {\r\n const id = createUniqueId();\r\n\r\n p = mergeProps({ color: '#6E56CF' } as const, p);\r\n\r\n return (\r\n <div class={cn('size-3 animate-spin', p.class)}>\r\n <svg\r\n width=\"inherit\"\r\n height=\"inherit\"\r\n viewBox=\"0 0 20 20\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n >\r\n <ellipse\r\n cx=\"9.99995\"\r\n cy=\"9.99995\"\r\n rx=\"7.31001\"\r\n ry=\"7.31001\"\r\n stroke={p.color}\r\n stroke-opacity=\"0.25\"\r\n stroke-width=\"4\"\r\n />\r\n <path\r\n d=\"M9.94939 2.69013C11.8881 2.67671 13.7527 3.43398 15.133 4.79535C16.5134 6.15671 17.2964 8.01067 17.3098 9.94936\"\r\n stroke={`url(#${id})`}\r\n stroke-width=\"4\"\r\n stroke-linecap=\"round\"\r\n stroke-dasharray=\"1.23 1.23\"\r\n />\r\n <defs>\r\n <linearGradient\r\n id={id}\r\n x1=\"16.3108\"\r\n y1=\"13.6892\"\r\n x2=\"3.68922\"\r\n y2=\"6.31075\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color={p.color} />\r\n <stop offset=\"0.5\" stop-color={p.color} stop-opacity=\"0.01\" />\r\n <stop offset=\"1\" stop-color={p.color} stop-opacity=\"0\" />\r\n </linearGradient>\r\n </defs>\r\n </svg>\r\n </div>\r\n );\r\n};\r\nconst LoadingSpinner3: Component<{ class?: string; color?: string }> = p => {\r\n p = mergeProps({ color: 'currentColor' } as const, p);\r\n return (\r\n <div class={cn('size-7 p-0', p.class)} style={{ color: p.color }}>\r\n <svg fill=\"currentColor\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <g>\r\n <circle cx=\"12\" cy=\"3\" r=\"1\">\r\n <animate\r\n id=\"_dcbb18\"\r\n begin=\"0;_84a13e.end-0.5s\"\r\n attributeName=\"r\"\r\n calcMode=\"spline\"\r\n dur=\"0.6s\"\r\n values=\"1;2;1\"\r\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\r\n />\r\n </circle>\r\n <circle cx=\"16.50\" cy=\"4.21\" r=\"1\">\r\n <animate\r\n id=\"_92c238\"\r\n begin=\"_dcbb18.begin+0.1s\"\r\n attributeName=\"r\"\r\n calcMode=\"spline\"\r\n dur=\"0.6s\"\r\n values=\"1;2;1\"\r\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\r\n />\r\n </circle>\r\n <circle cx=\"7.50\" cy=\"4.21\" r=\"1\">\r\n <animate\r\n id=\"_84a13e\"\r\n begin=\"_5abc3e.begin+0.1s\"\r\n attributeName=\"r\"\r\n calcMode=\"spline\"\r\n dur=\"0.6s\"\r\n values=\"1;2;1\"\r\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\r\n />\r\n </circle>\r\n <circle cx=\"19.79\" cy=\"7.50\" r=\"1\">\r\n <animate\r\n id=\"_9d19c8\"\r\n begin=\"_92c238.begin+0.1s\"\r\n attributeName=\"r\"\r\n calcMode=\"spline\"\r\n dur=\"0.6s\"\r\n values=\"1;2;1\"\r\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\r\n />\r\n </circle>\r\n <circle cx=\"4.21\" cy=\"7.50\" r=\"1\">\r\n <animate\r\n id=\"_5abc3e\"\r\n begin=\"_dcfbb2.begin+0.1s\"\r\n attributeName=\"r\"\r\n calcMode=\"spline\"\r\n dur=\"0.6s\"\r\n values=\"1;2;1\"\r\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\r\n />\r\n </circle>\r\n <circle cx=\"21.00\" cy=\"12.00\" r=\"1\">\r\n <animate\r\n id=\"_cf88a3\"\r\n begin=\"_9d19c8.begin+0.1s\"\r\n attributeName=\"r\"\r\n calcMode=\"spline\"\r\n dur=\"0.6s\"\r\n values=\"1;2;1\"\r\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\r\n />\r\n </circle>\r\n <circle cx=\"3.00\" cy=\"12.00\" r=\"1\">\r\n <animate\r\n id=\"_dcfbb2\"\r\n begin=\"_514e98.begin+0.1s\"\r\n attributeName=\"r\"\r\n calcMode=\"spline\"\r\n dur=\"0.6s\"\r\n values=\"1;2;1\"\r\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\r\n />\r\n </circle>\r\n <circle cx=\"19.79\" cy=\"16.50\" r=\"1\">\r\n <animate\r\n id=\"_2fecf8\"\r\n begin=\"_cf88a3.begin+0.1s\"\r\n attributeName=\"r\"\r\n calcMode=\"spline\"\r\n dur=\"0.6s\"\r\n values=\"1;2;1\"\r\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\r\n />\r\n </circle>\r\n <circle cx=\"4.21\" cy=\"16.50\" r=\"1\">\r\n <animate\r\n id=\"_514e98\"\r\n begin=\"_c4d048.begin+0.1s\"\r\n attributeName=\"r\"\r\n calcMode=\"spline\"\r\n dur=\"0.6s\"\r\n values=\"1;2;1\"\r\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\r\n />\r\n </circle>\r\n <circle cx=\"16.50\" cy=\"19.79\" r=\"1\">\r\n <animate\r\n id=\"_033759\"\r\n begin=\"_2fecf8.begin+0.1s\"\r\n attributeName=\"r\"\r\n calcMode=\"spline\"\r\n dur=\"0.6s\"\r\n values=\"1;2;1\"\r\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\r\n />\r\n </circle>\r\n <circle cx=\"7.50\" cy=\"19.79\" r=\"1\">\r\n <animate\r\n id=\"_c4d048\"\r\n begin=\"_3ec8bd.begin+0.1s\"\r\n attributeName=\"r\"\r\n calcMode=\"spline\"\r\n dur=\"0.6s\"\r\n values=\"1;2;1\"\r\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\r\n />\r\n </circle>\r\n <circle cx=\"12\" cy=\"21\" r=\"1\">\r\n <animate\r\n id=\"_3ec8bd\"\r\n begin=\"_033759.begin+0.1s\"\r\n attributeName=\"r\"\r\n calcMode=\"spline\"\r\n dur=\"0.6s\"\r\n values=\"1;2;1\"\r\n keySplines=\".27,.42,.37,.99;.53,0,.61,.73\"\r\n />\r\n </circle>\r\n <animateTransform\r\n attributeName=\"transform\"\r\n type=\"rotate\"\r\n dur=\"6s\"\r\n values=\"360 12 12;0 12 12\"\r\n repeatCount=\"indefinite\"\r\n />\r\n </g>\r\n </svg>\r\n </div>\r\n );\r\n};\r\nconst LoadingSpinner4: Component<{ class?: string; color?: string }> = p => {\r\n return <Loader class={cn('animate-spin', p.class)} color={p.color} />;\r\n};\r\nconst LoadingSpinner5: Component<{ class?: string; color?: string }> = p => {\r\n p = mergeProps({ class: 'size-6' } as const, p);\r\n return (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n x=\"0px\"\r\n y=\"0px\"\r\n viewBox=\"0 0 2400 2400\"\r\n class={p.class}\r\n style={{ color: p.color }}\r\n >\r\n <g stroke-width=\"200\" stroke-linecap=\"round\" stroke=\"currentColor\" fill=\"none\" id=\"spinner\">\r\n <line x1=\"1200\" y1=\"600\" x2=\"1200\" y2=\"100\" />\r\n <line opacity=\"0.5\" x1=\"1200\" y1=\"2300\" x2=\"1200\" y2=\"1800\" />\r\n <line opacity=\"0.917\" x1=\"900\" y1=\"680.4\" x2=\"650\" y2=\"247.4\" />\r\n <line opacity=\"0.417\" x1=\"1750\" y1=\"2152.6\" x2=\"1500\" y2=\"1719.6\" />\r\n <line opacity=\"0.833\" x1=\"680.4\" y1=\"900\" x2=\"247.4\" y2=\"650\" />\r\n <line opacity=\"0.333\" x1=\"2152.6\" y1=\"1750\" x2=\"1719.6\" y2=\"1500\" />\r\n <line opacity=\"0.75\" x1=\"600\" y1=\"1200\" x2=\"100\" y2=\"1200\" />\r\n <line opacity=\"0.25\" x1=\"2300\" y1=\"1200\" x2=\"1800\" y2=\"1200\" />\r\n <line opacity=\"0.667\" x1=\"680.4\" y1=\"1500\" x2=\"247.4\" y2=\"1750\" />\r\n <line opacity=\"0.167\" x1=\"2152.6\" y1=\"650\" x2=\"1719.6\" y2=\"900\" />\r\n <line opacity=\"0.583\" x1=\"900\" y1=\"1719.6\" x2=\"650\" y2=\"2152.6\" />\r\n <line opacity=\"0.083\" x1=\"1750\" y1=\"247.4\" x2=\"1500\" y2=\"680.4\" />\r\n <animateTransform\r\n attributeName=\"transform\"\r\n attributeType=\"XML\"\r\n type=\"rotate\"\r\n keyTimes=\"0;0.08333;0.16667;0.25;0.33333;0.41667;0.5;0.58333;0.66667;0.75;0.83333;0.91667\"\r\n values=\"0 1199 1199;30 1199 1199;60 1199 1199;90 1199 1199;120 1199 1199;150 1199 1199;180 1199 1199;210 1199 1199;240 1199 1199;270 1199 1199;300 1199 1199;330 1199 1199\"\r\n dur=\"0.83333s\"\r\n begin=\"0s\"\r\n repeatCount=\"indefinite\"\r\n calcMode=\"discrete\"\r\n />\r\n </g>\r\n </svg>\r\n );\r\n};\r\nconst LoadingSpinner6: Component<{ class?: string; color?: string }> = p => {\r\n p = mergeProps({ class: 'size-6' } as const, p);\r\n const id = createUniqueId();\r\n return (\r\n <svg\r\n fill=\"none\"\r\n viewBox=\"0 0 20 20\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n class={p.class}\r\n style={{ color: p.color }}\r\n >\r\n <defs>\r\n <linearGradient id={id}>\r\n <stop offset=\"0%\" stop-color=\"currentColor\" stop-opacity=\"1\" />\r\n <stop offset=\"100%\" stop-color=\"currentColor\" stop-opacity=\"0.25\" />\r\n </linearGradient>\r\n </defs>\r\n <circle\r\n cx=\"10\"\r\n cy=\"10\"\r\n r=\"8\"\r\n stroke-width=\"2\"\r\n class=\"animate-spin\"\r\n stroke={`url(#${id})`}\r\n fill=\"none\"\r\n style={{ 'transform-origin': '50% 50%' }}\r\n />\r\n </svg>\r\n );\r\n};\r\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mansory.js","names":["Accessor","Component","createEffect","createMemo","createRoot","createSignal","For","mergeProps","on","onCleanup","onMount","Show","untrack","cn","createThrottle","MansoryBreakpoint","MansoryItemLayout","MansoryProps","MansoryResponsive","MansoryVirtualOptions","BREAKPOINTS","Record","Exclude","sm","md","lg","xl","BP_KEYS","const","DEFAULT_COLUMNS","default","DEFAULT_GAP","GAP_CACHE_MAX","gapCache","Map","resolveResponsive","config","T","containerWidth","Array","isArray","map","i","length","key","undefined","measureGapPx","gapClass","container","HTMLElement","probe","document","createElement","className","style","display","gridTemplateColumns","appendChild","computed","getComputedStyle","gap","parseFloat","columnGap","removeChild","measureGapPxCached","has","get","value","size","firstKey","keys","next","delete","set","computeLayout","itemHeights","columns","gapPx","layouts","totalHeight","sortedByTop","cols","Math","max","totalGap","colWidth","colHeights","fill","minCol","c","left","top","height","item","index","width","push","j","splice","maxH","findFirstVisible","sorted","visTop","lo","hi","mid","MansoryItemProps","getLayoutAccessor","items","itemClass","children","onRegister","el","HTMLDivElement","onUnregister","MansoryItem","props","itemLayout","styles","l","wrapper","child","widthPx","transform","_el$","_tmpl$","_$use","unregisterItem","_$insert","_$effect","_p$","_v$","_v$2","_v$3","e","_$setAttribute","t","_$className","a","_$style","Mansory","rawProps","virtual","estimateItemHeight","loadMoreThreshold","containerEl","innerEl","setContainerWidth","setItemHeights","currentColumns","resolved","currentGapClass","setGapPx","trackGapClass","_","layout","layoutAccessors","layoutSetters","v","layoutDisposers","getOrCreateLayoutAccessor","layoutSignalRoot","dispose","initialValue","equals","b","disposeLayoutSignal","disposeAllLayoutSignals","values","clear","keyEntryCache","syncLayoutSetters","newLayouts","setter","virtualOpts","overscan","isVirtual","scrollTop","setScrollTop","rafId","pendingScrollTop","loadMoreCooldown","loadMoreTimer","ReturnType","setTimeout","pendingItemChanges","flushItemHeights","applyItemHeightChanges","snapshot","prev","hasChange","idx","h","cancelFlushItemHeights","cancel","itemRO","ResizeObserver","entries","entry","target","parseInt","dataset","mansoryIdx","contentBoxSize","blockSize","contentRect","disconnectItemResizeObserver","disconnect","applyContainerWidth","applyContainerWidthChange","containerRO","inlineSize","observe","disconnectContainerResizeObserver","itemElMap","registerItem","unobserve","len","prevLen","slice","checkLoadMore","currentScrollTop","onLoadMore","scrollHeight","clientHeight","clearTimeout","clearLoadMoreTimer","cancelPendingRaf","cancelAnimationFrame","handleScroll","requestAnimationFrame","allIndices","renderedIndices","viewportHeight","overscanPx","visBottom","start","indices","renderedKeys","getItemKey","activeKeys","Set","add","k","_el$2","_tmpl$3","_el$3","firstChild","_$addEventListener","_ref$","_ref$2","_$createComponent","each","when","_tmpl$2","_v$4","class","_v$5","_$setStyleProperty"],"sources":["../../../src/components/mansory/mansory.tsx"],"sourcesContent":["import {\n Accessor,\n Component,\n createEffect,\n createMemo,\n createRoot,\n createSignal,\n For,\n mergeProps,\n on,\n onCleanup,\n onMount,\n Show,\n untrack,\n} from 'solid-js';\nimport { cn } from '@utils/cn';\nimport { createThrottle } from '@utils/helper';\nimport type {\n MansoryBreakpoint,\n MansoryItemLayout,\n MansoryProps,\n MansoryResponsive,\n MansoryVirtualOptions,\n} from './mansory.types';\n\nconst BREAKPOINTS: Record<Exclude<MansoryBreakpoint, 'default'>, number> = {\n sm: 640,\n md: 768,\n lg: 1024,\n xl: 1280,\n '2xl': 1536,\n};\n\nconst BP_KEYS = ['sm', 'md', 'lg', 'xl', '2xl'] as const;\n\nconst DEFAULT_COLUMNS: MansoryResponsive<number> = {\n default: 1,\n sm: 2,\n md: 3,\n lg: 4,\n};\n\nconst DEFAULT_GAP = 'gap-4';\n\nconst GAP_CACHE_MAX = 50;\nconst gapCache = new Map<string, number>();\n\nfunction resolveResponsive<T>(config: T | MansoryResponsive<T>, containerWidth: number): T {\n if (typeof config !== 'object' || config === null || Array.isArray(config)) {\n return config as T;\n }\n\n const map = config as MansoryResponsive<T>;\n\n for (let i = BP_KEYS.length - 1; i >= 0; i--) {\n const key = BP_KEYS[i];\n if (containerWidth >= BREAKPOINTS[key] && map[key] !== undefined) {\n return map[key] as T;\n }\n }\n\n return (map.default ?? (typeof config === 'object' ? undefined : config)) as T;\n}\n\nfunction measureGapPx(gapClass: string, container: HTMLElement): number {\n const probe = document.createElement('div');\n probe.className = `ma06 ${gapClass}`;\n probe.style.display = 'grid';\n probe.style.gridTemplateColumns = '1fr 1fr';\n\n probe.appendChild(document.createElement('div'));\n probe.appendChild(document.createElement('div'));\n container.appendChild(probe);\n const computed = getComputedStyle(probe);\n const gap = parseFloat(computed.columnGap || computed.gap || '0');\n container.removeChild(probe);\n return gap;\n}\n\nfunction measureGapPxCached(gapClass: string, container: HTMLElement): number {\n if (gapCache.has(gapClass)) return gapCache.get(gapClass)!;\n const value = measureGapPx(gapClass, container);\n\n if (gapCache.size >= GAP_CACHE_MAX) {\n const firstKey = gapCache.keys().next().value;\n if (firstKey !== undefined) gapCache.delete(firstKey);\n }\n gapCache.set(gapClass, value);\n return value;\n}\n\nfunction computeLayout(\n itemHeights: number[],\n columns: number,\n containerWidth: number,\n gapPx: number,\n): { layouts: MansoryItemLayout[]; totalHeight: number; sortedByTop: MansoryItemLayout[] } {\n const cols = Math.max(1, columns);\n const totalGap = gapPx * (cols - 1);\n const colWidth = (containerWidth - totalGap) / cols;\n\n const colHeights = new Array<number>(cols).fill(0);\n const layouts: MansoryItemLayout[] = [];\n\n const sortedByTop: MansoryItemLayout[] = [];\n\n for (let i = 0; i < itemHeights.length; i++) {\n let minCol = 0;\n for (let c = 1; c < cols; c++) {\n if (colHeights[c] < colHeights[minCol]) minCol = c;\n }\n\n const left = minCol * (colWidth + gapPx);\n const top = colHeights[minCol];\n const height = itemHeights[i] ?? 0;\n\n const item: MansoryItemLayout = { index: i, top, left, width: colWidth, height };\n layouts.push(item);\n\n let j = sortedByTop.length - 1;\n while (j >= 0 && sortedByTop[j].top > top) j--;\n sortedByTop.splice(j + 1, 0, item);\n\n colHeights[minCol] = top + height + gapPx;\n }\n\n let maxH = 0;\n for (let i = 0; i < colHeights.length; i++) {\n if (colHeights[i] > maxH) maxH = colHeights[i];\n }\n\n return { layouts, totalHeight: maxH > 0 ? maxH - gapPx : 0, sortedByTop };\n}\n\nfunction findFirstVisible(sorted: MansoryItemLayout[], visTop: number): number {\n let lo = 0,\n hi = sorted.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (sorted[mid].top + sorted[mid].height < visTop) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n}\n\ninterface MansoryItemProps {\n index: number;\n getLayoutAccessor: (index: number) => Accessor<MansoryItemLayout | undefined>;\n items: unknown[];\n itemClass?: string;\n children: MansoryProps['children'];\n onRegister: (index: number, el: HTMLDivElement) => void;\n onUnregister: (index: number) => void;\n}\n\nconst MansoryItem: Component<MansoryItemProps> = props => {\n const itemLayout = props.getLayoutAccessor(props.index);\n\n const styles = createMemo(() => {\n const l = itemLayout();\n if (!l) return { wrapper: {} as Record<string, string>, child: {} as Record<string, string> };\n const widthPx = `${l.width}px`;\n return {\n wrapper: { width: widthPx, transform: `translate3d(${l.left}px, ${l.top}px, 0)` },\n child: { width: widthPx },\n };\n });\n\n return (\n <div\n ref={el => {\n props.onRegister(props.index, el);\n onCleanup(function unregisterItem() {\n props.onUnregister(props.index);\n });\n }}\n data-mansory-idx={props.index}\n class={cn('ma03 ma04', props.itemClass)}\n style={styles().wrapper}\n >\n {props.children(props.items[props.index], () => props.index, styles().child)}\n </div>\n );\n};\n\nexport const Mansory: Component<MansoryProps> = rawProps => {\n const props = mergeProps(\n {\n columns: DEFAULT_COLUMNS,\n gap: DEFAULT_GAP,\n virtual: false as boolean | MansoryVirtualOptions,\n estimateItemHeight: 200,\n loadMoreThreshold: 200,\n },\n rawProps,\n );\n\n let containerEl!: HTMLDivElement;\n let innerEl!: HTMLDivElement;\n\n const [containerWidth, setContainerWidth] = createSignal(0);\n const [itemHeights, setItemHeights] = createSignal<number[]>([]);\n\n const currentColumns = createMemo(() => {\n const resolved = resolveResponsive<number>(props.columns as number, containerWidth());\n return Math.max(1, resolved ?? 1);\n });\n\n const currentGapClass = createMemo(() => {\n const resolved = resolveResponsive<string>(props.gap as string, containerWidth());\n return resolved ?? 'gap-4';\n });\n\n const [gapPx, setGapPx] = createSignal(16);\n\n createEffect(function trackGapClass() {\n const _ = currentGapClass();\n if (containerEl) {\n setGapPx(measureGapPxCached(currentGapClass(), containerEl));\n }\n });\n\n const layout = createMemo(() =>\n computeLayout(itemHeights(), currentColumns(), containerWidth(), gapPx()),\n );\n\n const totalHeight = createMemo(() => layout().totalHeight);\n\n const layoutAccessors = new Map<number, Accessor<MansoryItemLayout | undefined>>();\n const layoutSetters = new Map<number, (v: MansoryItemLayout | undefined) => void>();\n const layoutDisposers = new Map<number, () => void>();\n\n function getOrCreateLayoutAccessor(index: number): Accessor<MansoryItemLayout | undefined> {\n if (!layoutAccessors.has(index)) {\n createRoot(function layoutSignalRoot(dispose) {\n layoutDisposers.set(index, dispose);\n const initialValue = untrack(() => layout().layouts[index]);\n const [get, set] = createSignal<MansoryItemLayout | undefined>(initialValue, {\n equals: (a, b) => {\n if (a === b) return true;\n if (!a || !b) return false;\n return (\n a.top === b.top && a.left === b.left && a.width === b.width && a.height === b.height\n );\n },\n });\n layoutAccessors.set(index, get);\n layoutSetters.set(index, set);\n });\n }\n return layoutAccessors.get(index)!;\n }\n\n function disposeLayoutSignal(index: number) {\n layoutDisposers.get(index)?.();\n layoutDisposers.delete(index);\n layoutAccessors.delete(index);\n layoutSetters.delete(index);\n }\n\n onCleanup(function disposeAllLayoutSignals() {\n for (const dispose of layoutDisposers.values()) dispose();\n layoutDisposers.clear();\n layoutAccessors.clear();\n layoutSetters.clear();\n keyEntryCache.clear();\n });\n\n createEffect(function syncLayoutSetters() {\n const newLayouts = layout().layouts;\n\n for (const [index, setter] of layoutSetters) {\n setter(newLayouts[index]);\n }\n });\n\n const virtualOpts = createMemo<MansoryVirtualOptions | null>(() => {\n const v = props.virtual;\n if (!v) return null;\n if (v === true) return { overscan: 5 };\n return { overscan: v.overscan ?? 5 };\n });\n\n const isVirtual = createMemo(() => virtualOpts() !== null);\n\n const [scrollTop, setScrollTop] = createSignal(0);\n\n let rafId: number | null = null;\n let pendingScrollTop = 0;\n\n let loadMoreCooldown = false;\n let loadMoreTimer: ReturnType<typeof setTimeout> | null = null;\n\n const pendingItemChanges = new Map<number, number>();\n\n const flushItemHeights = createThrottle(function applyItemHeightChanges() {\n if (pendingItemChanges.size === 0) return;\n const snapshot = new Map(pendingItemChanges);\n pendingItemChanges.clear();\n\n setItemHeights(prev => {\n let hasChange = false;\n for (const [idx, h] of snapshot) {\n if (prev[idx] !== h) {\n hasChange = true;\n break;\n }\n }\n if (!hasChange) return prev;\n\n const next = [...prev];\n for (const [idx, h] of snapshot) next[idx] = h;\n return next;\n });\n }, 100);\n\n onCleanup(function cancelFlushItemHeights() {\n flushItemHeights.cancel();\n });\n\n const itemRO = new ResizeObserver(entries => {\n for (const entry of entries) {\n const el = entry.target as HTMLDivElement;\n const idx = parseInt(el.dataset.mansoryIdx ?? '-1', 10);\n if (idx < 0) continue;\n\n const h = entry.contentBoxSize?.[0]?.blockSize ?? entry.contentRect.height;\n pendingItemChanges.set(idx, h);\n }\n\n flushItemHeights();\n });\n\n onCleanup(function disconnectItemResizeObserver() {\n itemRO.disconnect();\n });\n\n onMount(() => {\n const applyContainerWidth = createThrottle(function applyContainerWidthChange(width: number) {\n setContainerWidth(width);\n }, 100);\n\n const containerRO = new ResizeObserver(entries => {\n for (const entry of entries) {\n const width = entry.contentBoxSize?.[0]?.inlineSize ?? entry.contentRect.width;\n applyContainerWidth(width);\n }\n });\n containerRO.observe(containerEl);\n onCleanup(function disconnectContainerResizeObserver() {\n applyContainerWidth.cancel();\n containerRO.disconnect();\n });\n });\n\n const itemElMap = new Map<number, HTMLDivElement>();\n\n function registerItem(index: number, el: HTMLDivElement) {\n itemElMap.set(index, el);\n itemRO.observe(el);\n }\n\n function unregisterItem(index: number) {\n const el = itemElMap.get(index);\n if (el) {\n itemRO.unobserve(el);\n itemElMap.delete(index);\n }\n }\n\n createEffect(\n on(\n () => props.items.length,\n len => {\n setItemHeights(prev => {\n const prevLen = prev.length;\n if (prevLen === len) return prev;\n\n if (len > prevLen) {\n const next = [...prev];\n for (let i = prevLen; i < len; i++) next.push(props.estimateItemHeight);\n return next;\n }\n\n for (let i = len; i < prevLen; i++) {\n disposeLayoutSignal(i);\n }\n return prev.slice(0, len);\n });\n },\n ),\n );\n\n function checkLoadMore(currentScrollTop: number) {\n if (!props.onLoadMore || loadMoreCooldown) return;\n const { scrollHeight, clientHeight } = containerEl;\n if (currentScrollTop + clientHeight >= scrollHeight - props.loadMoreThreshold) {\n loadMoreCooldown = true;\n\n if (loadMoreTimer) clearTimeout(loadMoreTimer);\n loadMoreTimer = setTimeout(() => {\n loadMoreCooldown = false;\n loadMoreTimer = null;\n }, 10_000);\n props.onLoadMore();\n }\n }\n\n createEffect(\n on(\n () => props.items.length,\n () => {\n if (loadMoreTimer) {\n clearTimeout(loadMoreTimer);\n loadMoreTimer = null;\n }\n loadMoreCooldown = false;\n },\n ),\n );\n\n onCleanup(function clearLoadMoreTimer() {\n if (loadMoreTimer) clearTimeout(loadMoreTimer);\n });\n\n onCleanup(function cancelPendingRaf() {\n if (rafId !== null) cancelAnimationFrame(rafId);\n });\n\n function handleScroll() {\n pendingScrollTop = containerEl.scrollTop;\n\n if (rafId === null) {\n rafId = requestAnimationFrame(() => {\n rafId = null;\n setScrollTop(pendingScrollTop);\n checkLoadMore(pendingScrollTop);\n });\n }\n }\n\n const allIndices = createMemo<number[]>((prev = []) => {\n const len = props.items.length;\n if (len === prev.length) return prev;\n if (len > prev.length) {\n const next = [...prev];\n for (let i = prev.length; i < len; i++) next.push(i);\n return next;\n }\n return prev.slice(0, len);\n });\n\n const renderedIndices = createMemo(() => {\n if (!isVirtual()) {\n return allIndices();\n }\n\n if (containerWidth() === 0) return [];\n\n const currentScrollTop = scrollTop();\n const viewportHeight = containerEl.clientHeight;\n const overscan = virtualOpts()?.overscan ?? 5;\n const overscanPx = overscan * props.estimateItemHeight;\n const visTop = currentScrollTop - overscanPx;\n const visBottom = currentScrollTop + viewportHeight + overscanPx;\n\n const sorted = layout().sortedByTop;\n const start = findFirstVisible(sorted, visTop);\n const indices: number[] = [];\n for (let i = start; i < sorted.length; i++) {\n if (sorted[i].top > visBottom) break;\n indices.push(sorted[i].index);\n }\n return indices;\n });\n\n const keyEntryCache = new Map<string | number, { key: string | number; index: number }>();\n\n const renderedKeys = createMemo(() => {\n const indices = renderedIndices();\n if (!props.getItemKey) return indices;\n\n const activeKeys = new Set<string | number>();\n\n const entries = indices.map(i => {\n const key = props.getItemKey!(props.items[i], i);\n activeKeys.add(key);\n\n let entry = keyEntryCache.get(key);\n if (!entry) {\n entry = { key, index: i };\n keyEntryCache.set(key, entry);\n } else {\n entry.index = i;\n }\n return entry;\n });\n\n for (const k of keyEntryCache.keys()) {\n if (!activeKeys.has(k)) keyEntryCache.delete(k);\n }\n\n return entries;\n });\n\n return (\n <div\n ref={containerEl}\n class={cn('ma01', isVirtual() && 'ma05', props.class)}\n onScroll={isVirtual() || props.onLoadMore ? handleScroll : undefined}\n >\n <div ref={innerEl} class=\"ma02\" style={{ height: `${totalHeight()}px` }}>\n <For each={renderedKeys()}>\n {entry => {\n const index = typeof entry === 'number' ? entry : entry.index;\n return (\n <MansoryItem\n index={index}\n getLayoutAccessor={getOrCreateLayoutAccessor}\n items={props.items}\n itemClass={props.itemClass}\n onRegister={registerItem}\n onUnregister={unregisterItem}\n >\n {props.children}\n </MansoryItem>\n );\n }}\n </For>\n </div>\n\n <Show when={props.items.length === 0}>\n <div class=\"ma08\">No items</div>\n </Show>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mansory.js","names":["Accessor","Component","createEffect","createMemo","createRoot","createSignal","For","mergeProps","on","onCleanup","onMount","Show","untrack","cn","createThrottle","MansoryBreakpoint","MansoryItemLayout","MansoryProps","MansoryResponsive","MansoryVirtualOptions","BREAKPOINTS","Record","Exclude","sm","md","lg","xl","BP_KEYS","const","DEFAULT_COLUMNS","default","DEFAULT_GAP","GAP_CACHE_MAX","gapCache","Map","resolveResponsive","config","T","containerWidth","Array","isArray","map","i","length","key","undefined","measureGapPx","gapClass","container","HTMLElement","probe","document","createElement","className","style","display","gridTemplateColumns","appendChild","computed","getComputedStyle","gap","parseFloat","columnGap","removeChild","measureGapPxCached","has","get","value","size","firstKey","keys","next","delete","set","computeLayout","itemHeights","columns","gapPx","layouts","totalHeight","sortedByTop","cols","Math","max","totalGap","colWidth","colHeights","fill","minCol","c","left","top","height","item","index","width","push","j","splice","maxH","findFirstVisible","sorted","visTop","lo","hi","mid","MansoryItemProps","getLayoutAccessor","items","itemClass","children","onRegister","el","HTMLDivElement","onUnregister","MansoryItem","props","itemLayout","styles","l","wrapper","child","widthPx","transform","_el$","_tmpl$","_$use","unregisterItem","_$insert","_$effect","_p$","_v$","_v$2","_v$3","e","_$setAttribute","t","_$className","a","_$style","Mansory","rawProps","virtual","estimateItemHeight","loadMoreThreshold","containerEl","innerEl","setContainerWidth","setItemHeights","currentColumns","resolved","currentGapClass","setGapPx","trackGapClass","_","layout","layoutAccessors","layoutSetters","v","layoutDisposers","getOrCreateLayoutAccessor","layoutSignalRoot","dispose","initialValue","equals","b","disposeLayoutSignal","disposeAllLayoutSignals","values","clear","keyEntryCache","syncLayoutSetters","newLayouts","setter","virtualOpts","overscan","isVirtual","scrollTop","setScrollTop","rafId","pendingScrollTop","loadMoreCooldown","loadMoreTimer","ReturnType","setTimeout","pendingItemChanges","flushItemHeights","applyItemHeightChanges","snapshot","prev","hasChange","idx","h","cancelFlushItemHeights","cancel","itemRO","ResizeObserver","entries","entry","target","parseInt","dataset","mansoryIdx","contentBoxSize","blockSize","contentRect","disconnectItemResizeObserver","disconnect","applyContainerWidth","applyContainerWidthChange","containerRO","inlineSize","observe","disconnectContainerResizeObserver","itemElMap","registerItem","unobserve","len","prevLen","slice","checkLoadMore","currentScrollTop","onLoadMore","scrollHeight","clientHeight","clearTimeout","clearLoadMoreTimer","cancelPendingRaf","cancelAnimationFrame","handleScroll","requestAnimationFrame","allIndices","renderedIndices","viewportHeight","overscanPx","visBottom","start","indices","renderedKeys","getItemKey","activeKeys","Set","add","k","_el$2","_tmpl$3","_el$3","firstChild","_$addEventListener","_ref$","_ref$2","_$createComponent","each","when","_tmpl$2","_v$4","class","_v$5","_$setStyleProperty"],"sources":["../../../src/components/mansory/mansory.tsx"],"sourcesContent":["import {\r\n Accessor,\r\n Component,\r\n createEffect,\r\n createMemo,\r\n createRoot,\r\n createSignal,\r\n For,\r\n mergeProps,\r\n on,\r\n onCleanup,\r\n onMount,\r\n Show,\r\n untrack,\r\n} from 'solid-js';\r\nimport { cn } from '@utils/cn';\r\nimport { createThrottle } from '@utils/helper';\r\nimport type {\r\n MansoryBreakpoint,\r\n MansoryItemLayout,\r\n MansoryProps,\r\n MansoryResponsive,\r\n MansoryVirtualOptions,\r\n} from './mansory.types';\r\n\r\nconst BREAKPOINTS: Record<Exclude<MansoryBreakpoint, 'default'>, number> = {\r\n sm: 640,\r\n md: 768,\r\n lg: 1024,\r\n xl: 1280,\r\n '2xl': 1536,\r\n};\r\n\r\nconst BP_KEYS = ['sm', 'md', 'lg', 'xl', '2xl'] as const;\r\n\r\nconst DEFAULT_COLUMNS: MansoryResponsive<number> = {\r\n default: 1,\r\n sm: 2,\r\n md: 3,\r\n lg: 4,\r\n};\r\n\r\nconst DEFAULT_GAP = 'gap-4';\r\n\r\nconst GAP_CACHE_MAX = 50;\r\nconst gapCache = new Map<string, number>();\r\n\r\nfunction resolveResponsive<T>(config: T | MansoryResponsive<T>, containerWidth: number): T {\r\n if (typeof config !== 'object' || config === null || Array.isArray(config)) {\r\n return config as T;\r\n }\r\n\r\n const map = config as MansoryResponsive<T>;\r\n\r\n for (let i = BP_KEYS.length - 1; i >= 0; i--) {\r\n const key = BP_KEYS[i];\r\n if (containerWidth >= BREAKPOINTS[key] && map[key] !== undefined) {\r\n return map[key] as T;\r\n }\r\n }\r\n\r\n return (map.default ?? (typeof config === 'object' ? undefined : config)) as T;\r\n}\r\n\r\nfunction measureGapPx(gapClass: string, container: HTMLElement): number {\r\n const probe = document.createElement('div');\r\n probe.className = `ma06 ${gapClass}`;\r\n probe.style.display = 'grid';\r\n probe.style.gridTemplateColumns = '1fr 1fr';\r\n\r\n probe.appendChild(document.createElement('div'));\r\n probe.appendChild(document.createElement('div'));\r\n container.appendChild(probe);\r\n const computed = getComputedStyle(probe);\r\n const gap = parseFloat(computed.columnGap || computed.gap || '0');\r\n container.removeChild(probe);\r\n return gap;\r\n}\r\n\r\nfunction measureGapPxCached(gapClass: string, container: HTMLElement): number {\r\n if (gapCache.has(gapClass)) return gapCache.get(gapClass)!;\r\n const value = measureGapPx(gapClass, container);\r\n\r\n if (gapCache.size >= GAP_CACHE_MAX) {\r\n const firstKey = gapCache.keys().next().value;\r\n if (firstKey !== undefined) gapCache.delete(firstKey);\r\n }\r\n gapCache.set(gapClass, value);\r\n return value;\r\n}\r\n\r\nfunction computeLayout(\r\n itemHeights: number[],\r\n columns: number,\r\n containerWidth: number,\r\n gapPx: number,\r\n): { layouts: MansoryItemLayout[]; totalHeight: number; sortedByTop: MansoryItemLayout[] } {\r\n const cols = Math.max(1, columns);\r\n const totalGap = gapPx * (cols - 1);\r\n const colWidth = (containerWidth - totalGap) / cols;\r\n\r\n const colHeights = new Array<number>(cols).fill(0);\r\n const layouts: MansoryItemLayout[] = [];\r\n\r\n const sortedByTop: MansoryItemLayout[] = [];\r\n\r\n for (let i = 0; i < itemHeights.length; i++) {\r\n let minCol = 0;\r\n for (let c = 1; c < cols; c++) {\r\n if (colHeights[c] < colHeights[minCol]) minCol = c;\r\n }\r\n\r\n const left = minCol * (colWidth + gapPx);\r\n const top = colHeights[minCol];\r\n const height = itemHeights[i] ?? 0;\r\n\r\n const item: MansoryItemLayout = { index: i, top, left, width: colWidth, height };\r\n layouts.push(item);\r\n\r\n let j = sortedByTop.length - 1;\r\n while (j >= 0 && sortedByTop[j].top > top) j--;\r\n sortedByTop.splice(j + 1, 0, item);\r\n\r\n colHeights[minCol] = top + height + gapPx;\r\n }\r\n\r\n let maxH = 0;\r\n for (let i = 0; i < colHeights.length; i++) {\r\n if (colHeights[i] > maxH) maxH = colHeights[i];\r\n }\r\n\r\n return { layouts, totalHeight: maxH > 0 ? maxH - gapPx : 0, sortedByTop };\r\n}\r\n\r\nfunction findFirstVisible(sorted: MansoryItemLayout[], visTop: number): number {\r\n let lo = 0,\r\n hi = sorted.length;\r\n while (lo < hi) {\r\n const mid = (lo + hi) >> 1;\r\n if (sorted[mid].top + sorted[mid].height < visTop) lo = mid + 1;\r\n else hi = mid;\r\n }\r\n return lo;\r\n}\r\n\r\ninterface MansoryItemProps {\r\n index: number;\r\n getLayoutAccessor: (index: number) => Accessor<MansoryItemLayout | undefined>;\r\n items: unknown[];\r\n itemClass?: string;\r\n children: MansoryProps['children'];\r\n onRegister: (index: number, el: HTMLDivElement) => void;\r\n onUnregister: (index: number) => void;\r\n}\r\n\r\nconst MansoryItem: Component<MansoryItemProps> = props => {\r\n const itemLayout = props.getLayoutAccessor(props.index);\r\n\r\n const styles = createMemo(() => {\r\n const l = itemLayout();\r\n if (!l) return { wrapper: {} as Record<string, string>, child: {} as Record<string, string> };\r\n const widthPx = `${l.width}px`;\r\n return {\r\n wrapper: { width: widthPx, transform: `translate3d(${l.left}px, ${l.top}px, 0)` },\r\n child: { width: widthPx },\r\n };\r\n });\r\n\r\n return (\r\n <div\r\n ref={el => {\r\n props.onRegister(props.index, el);\r\n onCleanup(function unregisterItem() {\r\n props.onUnregister(props.index);\r\n });\r\n }}\r\n data-mansory-idx={props.index}\r\n class={cn('ma03 ma04', props.itemClass)}\r\n style={styles().wrapper}\r\n >\r\n {props.children(props.items[props.index], () => props.index, styles().child)}\r\n </div>\r\n );\r\n};\r\n\r\nexport const Mansory: Component<MansoryProps> = rawProps => {\r\n const props = mergeProps(\r\n {\r\n columns: DEFAULT_COLUMNS,\r\n gap: DEFAULT_GAP,\r\n virtual: false as boolean | MansoryVirtualOptions,\r\n estimateItemHeight: 200,\r\n loadMoreThreshold: 200,\r\n },\r\n rawProps,\r\n );\r\n\r\n let containerEl!: HTMLDivElement;\r\n let innerEl!: HTMLDivElement;\r\n\r\n const [containerWidth, setContainerWidth] = createSignal(0);\r\n const [itemHeights, setItemHeights] = createSignal<number[]>([]);\r\n\r\n const currentColumns = createMemo(() => {\r\n const resolved = resolveResponsive<number>(props.columns as number, containerWidth());\r\n return Math.max(1, resolved ?? 1);\r\n });\r\n\r\n const currentGapClass = createMemo(() => {\r\n const resolved = resolveResponsive<string>(props.gap as string, containerWidth());\r\n return resolved ?? 'gap-4';\r\n });\r\n\r\n const [gapPx, setGapPx] = createSignal(16);\r\n\r\n createEffect(function trackGapClass() {\r\n const _ = currentGapClass();\r\n if (containerEl) {\r\n setGapPx(measureGapPxCached(currentGapClass(), containerEl));\r\n }\r\n });\r\n\r\n const layout = createMemo(() =>\r\n computeLayout(itemHeights(), currentColumns(), containerWidth(), gapPx()),\r\n );\r\n\r\n const totalHeight = createMemo(() => layout().totalHeight);\r\n\r\n const layoutAccessors = new Map<number, Accessor<MansoryItemLayout | undefined>>();\r\n const layoutSetters = new Map<number, (v: MansoryItemLayout | undefined) => void>();\r\n const layoutDisposers = new Map<number, () => void>();\r\n\r\n function getOrCreateLayoutAccessor(index: number): Accessor<MansoryItemLayout | undefined> {\r\n if (!layoutAccessors.has(index)) {\r\n createRoot(function layoutSignalRoot(dispose) {\r\n layoutDisposers.set(index, dispose);\r\n const initialValue = untrack(() => layout().layouts[index]);\r\n const [get, set] = createSignal<MansoryItemLayout | undefined>(initialValue, {\r\n equals: (a, b) => {\r\n if (a === b) return true;\r\n if (!a || !b) return false;\r\n return (\r\n a.top === b.top && a.left === b.left && a.width === b.width && a.height === b.height\r\n );\r\n },\r\n });\r\n layoutAccessors.set(index, get);\r\n layoutSetters.set(index, set);\r\n });\r\n }\r\n return layoutAccessors.get(index)!;\r\n }\r\n\r\n function disposeLayoutSignal(index: number) {\r\n layoutDisposers.get(index)?.();\r\n layoutDisposers.delete(index);\r\n layoutAccessors.delete(index);\r\n layoutSetters.delete(index);\r\n }\r\n\r\n onCleanup(function disposeAllLayoutSignals() {\r\n for (const dispose of layoutDisposers.values()) dispose();\r\n layoutDisposers.clear();\r\n layoutAccessors.clear();\r\n layoutSetters.clear();\r\n keyEntryCache.clear();\r\n });\r\n\r\n createEffect(function syncLayoutSetters() {\r\n const newLayouts = layout().layouts;\r\n\r\n for (const [index, setter] of layoutSetters) {\r\n setter(newLayouts[index]);\r\n }\r\n });\r\n\r\n const virtualOpts = createMemo<MansoryVirtualOptions | null>(() => {\r\n const v = props.virtual;\r\n if (!v) return null;\r\n if (v === true) return { overscan: 5 };\r\n return { overscan: v.overscan ?? 5 };\r\n });\r\n\r\n const isVirtual = createMemo(() => virtualOpts() !== null);\r\n\r\n const [scrollTop, setScrollTop] = createSignal(0);\r\n\r\n let rafId: number | null = null;\r\n let pendingScrollTop = 0;\r\n\r\n let loadMoreCooldown = false;\r\n let loadMoreTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\n const pendingItemChanges = new Map<number, number>();\r\n\r\n const flushItemHeights = createThrottle(function applyItemHeightChanges() {\r\n if (pendingItemChanges.size === 0) return;\r\n const snapshot = new Map(pendingItemChanges);\r\n pendingItemChanges.clear();\r\n\r\n setItemHeights(prev => {\r\n let hasChange = false;\r\n for (const [idx, h] of snapshot) {\r\n if (prev[idx] !== h) {\r\n hasChange = true;\r\n break;\r\n }\r\n }\r\n if (!hasChange) return prev;\r\n\r\n const next = [...prev];\r\n for (const [idx, h] of snapshot) next[idx] = h;\r\n return next;\r\n });\r\n }, 100);\r\n\r\n onCleanup(function cancelFlushItemHeights() {\r\n flushItemHeights.cancel();\r\n });\r\n\r\n const itemRO = new ResizeObserver(entries => {\r\n for (const entry of entries) {\r\n const el = entry.target as HTMLDivElement;\r\n const idx = parseInt(el.dataset.mansoryIdx ?? '-1', 10);\r\n if (idx < 0) continue;\r\n\r\n const h = entry.contentBoxSize?.[0]?.blockSize ?? entry.contentRect.height;\r\n pendingItemChanges.set(idx, h);\r\n }\r\n\r\n flushItemHeights();\r\n });\r\n\r\n onCleanup(function disconnectItemResizeObserver() {\r\n itemRO.disconnect();\r\n });\r\n\r\n onMount(() => {\r\n const applyContainerWidth = createThrottle(function applyContainerWidthChange(width: number) {\r\n setContainerWidth(width);\r\n }, 100);\r\n\r\n const containerRO = new ResizeObserver(entries => {\r\n for (const entry of entries) {\r\n const width = entry.contentBoxSize?.[0]?.inlineSize ?? entry.contentRect.width;\r\n applyContainerWidth(width);\r\n }\r\n });\r\n containerRO.observe(containerEl);\r\n onCleanup(function disconnectContainerResizeObserver() {\r\n applyContainerWidth.cancel();\r\n containerRO.disconnect();\r\n });\r\n });\r\n\r\n const itemElMap = new Map<number, HTMLDivElement>();\r\n\r\n function registerItem(index: number, el: HTMLDivElement) {\r\n itemElMap.set(index, el);\r\n itemRO.observe(el);\r\n }\r\n\r\n function unregisterItem(index: number) {\r\n const el = itemElMap.get(index);\r\n if (el) {\r\n itemRO.unobserve(el);\r\n itemElMap.delete(index);\r\n }\r\n }\r\n\r\n createEffect(\r\n on(\r\n () => props.items.length,\r\n len => {\r\n setItemHeights(prev => {\r\n const prevLen = prev.length;\r\n if (prevLen === len) return prev;\r\n\r\n if (len > prevLen) {\r\n const next = [...prev];\r\n for (let i = prevLen; i < len; i++) next.push(props.estimateItemHeight);\r\n return next;\r\n }\r\n\r\n for (let i = len; i < prevLen; i++) {\r\n disposeLayoutSignal(i);\r\n }\r\n return prev.slice(0, len);\r\n });\r\n },\r\n ),\r\n );\r\n\r\n function checkLoadMore(currentScrollTop: number) {\r\n if (!props.onLoadMore || loadMoreCooldown) return;\r\n const { scrollHeight, clientHeight } = containerEl;\r\n if (currentScrollTop + clientHeight >= scrollHeight - props.loadMoreThreshold) {\r\n loadMoreCooldown = true;\r\n\r\n if (loadMoreTimer) clearTimeout(loadMoreTimer);\r\n loadMoreTimer = setTimeout(() => {\r\n loadMoreCooldown = false;\r\n loadMoreTimer = null;\r\n }, 10_000);\r\n props.onLoadMore();\r\n }\r\n }\r\n\r\n createEffect(\r\n on(\r\n () => props.items.length,\r\n () => {\r\n if (loadMoreTimer) {\r\n clearTimeout(loadMoreTimer);\r\n loadMoreTimer = null;\r\n }\r\n loadMoreCooldown = false;\r\n },\r\n ),\r\n );\r\n\r\n onCleanup(function clearLoadMoreTimer() {\r\n if (loadMoreTimer) clearTimeout(loadMoreTimer);\r\n });\r\n\r\n onCleanup(function cancelPendingRaf() {\r\n if (rafId !== null) cancelAnimationFrame(rafId);\r\n });\r\n\r\n function handleScroll() {\r\n pendingScrollTop = containerEl.scrollTop;\r\n\r\n if (rafId === null) {\r\n rafId = requestAnimationFrame(() => {\r\n rafId = null;\r\n setScrollTop(pendingScrollTop);\r\n checkLoadMore(pendingScrollTop);\r\n });\r\n }\r\n }\r\n\r\n const allIndices = createMemo<number[]>((prev = []) => {\r\n const len = props.items.length;\r\n if (len === prev.length) return prev;\r\n if (len > prev.length) {\r\n const next = [...prev];\r\n for (let i = prev.length; i < len; i++) next.push(i);\r\n return next;\r\n }\r\n return prev.slice(0, len);\r\n });\r\n\r\n const renderedIndices = createMemo(() => {\r\n if (!isVirtual()) {\r\n return allIndices();\r\n }\r\n\r\n if (containerWidth() === 0) return [];\r\n\r\n const currentScrollTop = scrollTop();\r\n const viewportHeight = containerEl.clientHeight;\r\n const overscan = virtualOpts()?.overscan ?? 5;\r\n const overscanPx = overscan * props.estimateItemHeight;\r\n const visTop = currentScrollTop - overscanPx;\r\n const visBottom = currentScrollTop + viewportHeight + overscanPx;\r\n\r\n const sorted = layout().sortedByTop;\r\n const start = findFirstVisible(sorted, visTop);\r\n const indices: number[] = [];\r\n for (let i = start; i < sorted.length; i++) {\r\n if (sorted[i].top > visBottom) break;\r\n indices.push(sorted[i].index);\r\n }\r\n return indices;\r\n });\r\n\r\n const keyEntryCache = new Map<string | number, { key: string | number; index: number }>();\r\n\r\n const renderedKeys = createMemo(() => {\r\n const indices = renderedIndices();\r\n if (!props.getItemKey) return indices;\r\n\r\n const activeKeys = new Set<string | number>();\r\n\r\n const entries = indices.map(i => {\r\n const key = props.getItemKey!(props.items[i], i);\r\n activeKeys.add(key);\r\n\r\n let entry = keyEntryCache.get(key);\r\n if (!entry) {\r\n entry = { key, index: i };\r\n keyEntryCache.set(key, entry);\r\n } else {\r\n entry.index = i;\r\n }\r\n return entry;\r\n });\r\n\r\n for (const k of keyEntryCache.keys()) {\r\n if (!activeKeys.has(k)) keyEntryCache.delete(k);\r\n }\r\n\r\n return entries;\r\n });\r\n\r\n return (\r\n <div\r\n ref={containerEl}\r\n class={cn('ma01', isVirtual() && 'ma05', props.class)}\r\n onScroll={isVirtual() || props.onLoadMore ? handleScroll : undefined}\r\n >\r\n <div ref={innerEl} class=\"ma02\" style={{ height: `${totalHeight()}px` }}>\r\n <For each={renderedKeys()}>\r\n {entry => {\r\n const index = typeof entry === 'number' ? entry : entry.index;\r\n return (\r\n <MansoryItem\r\n index={index}\r\n getLayoutAccessor={getOrCreateLayoutAccessor}\r\n items={props.items}\r\n itemClass={props.itemClass}\r\n onRegister={registerItem}\r\n onUnregister={unregisterItem}\r\n >\r\n {props.children}\r\n </MansoryItem>\r\n );\r\n }}\r\n </For>\r\n </div>\r\n\r\n <Show when={props.items.length === 0}>\r\n <div class=\"ma08\">No items</div>\r\n </Show>\r\n </div>\r\n );\r\n};\r\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu.js","names":["cn","getColor","cva","VariantProps","RefreshCw","Accessor","Component","createEffect","createMemo","createSignal","createUniqueId","For","JSXElement","mergeProps","on","onCleanup","onMount","Setter","Show","Button","FolderItem","ItemClickInfo","MenuErrorInfo","MenuItem","MenuProps","menuVariants","variants","size","xs","sm","md","lg","xl","direction","vertical","horizontal","MenuVariantsProps","NodeRegistry","parentMap","Map","register","id","parentId","set","getPath","path","currentId","unshift","get","has","clear","LazyFolderRegistry","refreshFns","refreshFn","unregister","delete","refresh","fn","refreshAll","forEach","LazyFolderContent","item","renderItems","shouldLoad","isLoading","setIsLoading","onLoadError","error","onRegisterRefresh","props","loadedItems","setLoadedItems","loadItems","force","lazyItems","items","e","defer","_$createComponent","when","children","each","subItem","ACTIVE_CLASSNAME","Menu","p","color","highlightActive","const","ulRootRef","HTMLUListElement","nodeRegistry","lazyFolderRegistry","addActiveClassForId","length","elements","Array","from","getElementsByClassName","el","classList","remove","nodeId","document","getElementById","add","expandPathToId","element","details","querySelector","HTMLDetailsElement","open","focusById","console","warn","collapseById","refreshById","collapseAll","detailsList","querySelectorAll","d","expandedAll","collapseOtherRootFolders","exceptId","rootFolders","li","parentElement","itemId","type","folderItem","defaultExpanded","isLazyFolder","undefined","setShouldLoad","detailsRef","handleToggle","Event","currentTarget","isExpanded","preventDefault","handleLoadError","onError","errorInfo","source","message","Error","handleFolderClick","MouseEvent","stopPropagation","disabled","currentIsExpanded","willExpand","setTimeout","onItemClick","info","data","_el$","_tmpl$2","_el$2","firstChild","_el$3","_el$5","nextSibling","_$setAttribute","addEventListener","_ref$","_$use","$$click","_$insert","content","Element","_tmpl$","fallback","_$effect","_p$","_v$","class","itemWrap","_v$2","_v$3","itemHeader","_$className","t","a","handleFileClick","_el$6","_tmpl$3","_el$7","handleTitleClick","contains","_el$8","_tmpl$4","_el$9","_el$0","isLazyRoot","rootItems","setRootItems","isRootLoading","setIsRootLoading","clearMenuRegistries","loadRootItems","menuClass","root","setMenuFunction","_el$1","_tmpl$5","_$memo","_el$11","_tmpl$7","_el$12","icon","variant","onClick","_el$10","_tmpl$6","ele","_$spread","_$mergeProps","_$delegateEvents"],"sources":["../../../src/components/menu/menu.tsx"],"sourcesContent":["import { cn } from '@/utils/cn';\nimport { getColor } from '@/utils/helper';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport RefreshCw from 'lucide-solid/icons/refresh-cw';\nimport {\n Accessor,\n Component,\n createEffect,\n createMemo,\n createSignal,\n createUniqueId,\n For,\n JSXElement,\n mergeProps,\n on,\n onCleanup,\n onMount,\n Setter,\n Show,\n} from 'solid-js';\nimport { Button } from '../button';\nimport type { FolderItem, ItemClickInfo, MenuErrorInfo, MenuItem, MenuProps } from './menu.types';\n\nconst menuVariants = cva('menu', {\n variants: {\n size: { xs: 'menu-xs', sm: 'menu-sm', md: 'menu-md', lg: 'menu-lg', xl: 'menu-xl' },\n direction: { vertical: 'menu-vertical', horizontal: 'menu-horizontal' },\n },\n});\n\nexport type MenuVariantsProps = VariantProps<typeof menuVariants>;\n\nclass NodeRegistry {\n private parentMap = new Map<string, string | null>();\n register(id: string, parentId: string | null) {\n this.parentMap.set(id, parentId);\n }\n getPath(id: string): string[] {\n const path: string[] = [];\n let currentId: string | null | undefined = id;\n while (currentId != null) {\n path.unshift(currentId);\n currentId = this.parentMap.get(currentId);\n }\n return path;\n }\n has(id: string): boolean {\n return this.parentMap.has(id);\n }\n clear() {\n this.parentMap.clear();\n }\n}\n\nclass LazyFolderRegistry {\n private refreshFns = new Map<string, () => void>();\n register(id: string, refreshFn: () => void) {\n this.refreshFns.set(id, refreshFn);\n }\n unregister(id: string) {\n this.refreshFns.delete(id);\n }\n refresh(id: string) {\n const fn = this.refreshFns.get(id);\n if (fn) fn();\n }\n refreshAll() {\n this.refreshFns.forEach(fn => fn());\n }\n has(id: string): boolean {\n return this.refreshFns.has(id);\n }\n clear() {\n this.refreshFns.clear();\n }\n}\n\nconst LazyFolderContent: Component<{\n item: FolderItem;\n renderItems: (item: MenuItem, parentId: string | null) => JSXElement;\n parentId: string | null;\n shouldLoad: Accessor<boolean>;\n isLoading: Accessor<boolean>;\n setIsLoading: Setter<boolean>;\n onLoadError: (error: unknown) => void;\n onRegisterRefresh: (refreshFn: () => void) => void;\n}> = props => {\n const [loadedItems, setLoadedItems] = createSignal<MenuItem[] | null>(null);\n const loadItems = async (force = false) => {\n if (props.isLoading()) return;\n if (loadedItems() !== null && !force) return;\n if (!props.item.lazyItems) return;\n props.setIsLoading(true);\n try {\n const items = await props.item.lazyItems();\n setLoadedItems(items);\n } catch (e) {\n props.onLoadError(e);\n } finally {\n props.setIsLoading(false);\n }\n };\n const refresh = () => {\n loadItems(true);\n };\n onMount(() => {\n props.onRegisterRefresh(refresh);\n });\n createEffect(\n on(\n () => props.shouldLoad(),\n shouldLoad => {\n if (shouldLoad && loadedItems() === null) {\n loadItems();\n }\n },\n { defer: true },\n ),\n );\n return (\n <Show when={loadedItems()}>\n <For each={loadedItems()!}>{subItem => props.renderItems(subItem, props.parentId)}</For>\n </Show>\n );\n};\n\nconst ACTIVE_CLASSNAME = '_6ca32a';\nexport const Menu: Component<MenuProps> = p => {\n p = mergeProps(\n { size: 'md', direction: 'vertical', color: 'secondary', highlightActive: true } as const,\n p,\n );\n let ulRootRef: HTMLUListElement;\n const nodeRegistry = new NodeRegistry();\n const lazyFolderRegistry = new LazyFolderRegistry();\n function addActiveClassForId(id: string) {\n if (!ulRootRef || !p.highlightActive) return;\n const path = nodeRegistry.getPath(id);\n if (path.length === 0) return;\n\n const elements = Array.from(ulRootRef.getElementsByClassName(ACTIVE_CLASSNAME));\n\n for (const el of elements) el.classList.remove(ACTIVE_CLASSNAME);\n for (const nodeId of path) document.getElementById(nodeId)?.classList?.add(ACTIVE_CLASSNAME);\n }\n function expandPathToId(id: string) {\n const path = nodeRegistry.getPath(id);\n for (const nodeId of path) {\n const element = document.getElementById(nodeId);\n if (!element) continue;\n const details = element.querySelector(':scope > details') as HTMLDetailsElement | null;\n if (details && !details.open) {\n details.open = true;\n }\n }\n }\n function focusById(id: string) {\n if (!nodeRegistry.has(id)) {\n console.warn(`Menu.focusById: Node with id \"${id}\" not found in registry`);\n return;\n }\n expandPathToId(id);\n addActiveClassForId(id);\n }\n function collapseById(id: string) {\n const element = document.getElementById(id);\n if (!element) {\n console.warn(`Menu.collapseById: Element with id \"${id}\" not found`);\n return;\n }\n const details = element.querySelector(':scope > details') as HTMLDetailsElement | null;\n if (details) {\n details.open = false;\n const elements = details.getElementsByClassName(ACTIVE_CLASSNAME);\n for (const el of elements) el.classList.remove(ACTIVE_CLASSNAME);\n element.classList.remove(ACTIVE_CLASSNAME);\n }\n }\n function refreshById(id: string) {\n if (!lazyFolderRegistry.has(id)) {\n console.warn(`Menu.refreshById: Lazy folder with id \"${id}\" not found`);\n return;\n }\n lazyFolderRegistry.refresh(id);\n }\n function refreshAll() {\n lazyFolderRegistry.refreshAll();\n }\n function collapseAll() {\n if (!ulRootRef) return;\n const detailsList = ulRootRef.querySelectorAll('details');\n detailsList.forEach(d => (d.open = false));\n }\n function expandedAll() {\n if (!ulRootRef) return;\n const detailsList = ulRootRef.querySelectorAll('details');\n detailsList.forEach(d => (d.open = true));\n }\n function collapseOtherRootFolders(exceptId: string) {\n if (!ulRootRef) return;\n // Only collapse direct children (level 1 folders)\n const rootFolders = ulRootRef.querySelectorAll(':scope > li.folder > details');\n rootFolders.forEach(details => {\n const li = details.parentElement;\n if (li && li.id !== exceptId && (details as HTMLDetailsElement).open) {\n (details as HTMLDetailsElement).open = false;\n }\n });\n }\n function renderItems(item: MenuItem, parentId: string | null = null) {\n const itemId = item.id ?? createUniqueId();\n nodeRegistry.register(itemId, parentId);\n\n if (item.type === 'folder') {\n const folderItem = mergeProps(\n { defaultExpanded: item.defaultExpanded ?? p.defaultExpanded ?? false },\n item,\n { id: itemId },\n );\n const isLazyFolder = folderItem.lazyItems !== undefined;\n const [shouldLoad, setShouldLoad] = createSignal(folderItem.defaultExpanded);\n const [isLoading, setIsLoading] = createSignal(false);\n let detailsRef: HTMLDetailsElement | undefined;\n\n const handleToggle = (e: Event) => {\n const details = e.currentTarget as HTMLDetailsElement;\n const isExpanded = details.open;\n if (isLoading()) {\n e.preventDefault();\n return;\n }\n if (isLazyFolder) {\n setShouldLoad(isExpanded);\n }\n };\n\n const handleLoadError = (error: unknown) => {\n if (detailsRef) {\n detailsRef.open = false;\n }\n setShouldLoad(false);\n if (p.onError) {\n const errorInfo: MenuErrorInfo = {\n source: 'folder',\n itemId,\n path: nodeRegistry.getPath(itemId),\n error,\n message: error instanceof Error ? error.message : 'Failed to load folder items',\n };\n p.onError(errorInfo);\n }\n };\n\n const handleFolderClick = (e: MouseEvent) => {\n e.stopPropagation();\n if (isLoading() || item.disabled) {\n e.preventDefault();\n return;\n }\n\n const currentIsExpanded = detailsRef?.open ?? folderItem.defaultExpanded;\n const willExpand = !currentIsExpanded;\n\n // In horizontal mode, collapse other root folders when expanding a root folder\n if (p.direction === 'horizontal' && parentId === null && willExpand) {\n collapseOtherRootFolders(itemId);\n }\n\n if (detailsRef?.open === false) {\n addActiveClassForId(itemId);\n } else {\n setTimeout(() => {\n collapseById(itemId);\n });\n }\n\n if (p.onItemClick) {\n const isExpanded = willExpand;\n const info: ItemClickInfo = {\n id: itemId,\n path: nodeRegistry.getPath(itemId),\n type: 'folder',\n isExpanded,\n data: item.data,\n };\n p.onItemClick(info);\n }\n };\n return (\n <li\n class={cn(\n 'folder',\n (folderItem.disabled || isLoading()) && 'menu-disabled',\n p.class?.itemWrap,\n )}\n id={itemId}\n >\n <details ref={detailsRef} open={folderItem.defaultExpanded} onToggle={handleToggle}>\n <summary\n class={cn(isLoading() && 'after:hidden', p.class?.itemHeader)}\n onClick={handleFolderClick}\n >\n {folderItem.content as Element}\n <Show when={isLoading()}>\n <span class=\"loading loading-spinner loading-xs\"></span>\n </Show>\n </summary>\n <ul>\n <Show\n when={isLazyFolder}\n fallback={\n <For each={(folderItem as { items: MenuItem[] }).items}>\n {subItem => renderItems(subItem, itemId)}\n </For>\n }\n >\n <LazyFolderContent\n {...{\n renderItems,\n shouldLoad,\n isLoading,\n setIsLoading,\n item: folderItem,\n parentId: itemId,\n onLoadError: handleLoadError,\n onRegisterRefresh: refreshFn => lazyFolderRegistry.register(itemId, refreshFn),\n }}\n />\n </Show>\n </ul>\n </details>\n </li>\n );\n }\n if (item.type === 'file') {\n const handleFileClick = (e: MouseEvent) => {\n e.stopPropagation();\n addActiveClassForId(itemId);\n\n if (p.onItemClick) {\n const info: ItemClickInfo = {\n id: itemId,\n path: nodeRegistry.getPath(itemId),\n type: 'file',\n ...(item.data && { data: item.data }),\n };\n p.onItemClick(info);\n }\n };\n return (\n <li\n class={cn('file', item.disabled && 'menu-disabled', p.class?.itemWrap)}\n id={itemId}\n tabindex=\"0\"\n onClick={handleFileClick}\n >\n <div>{item.content as Element}</div>\n </li>\n );\n }\n if (item.type === 'title') {\n const handleTitleClick = (e: MouseEvent) => {\n e.stopPropagation();\n\n const li = document.getElementById(itemId);\n if (li && li.classList.contains(ACTIVE_CLASSNAME)) {\n const elements = li.getElementsByClassName(ACTIVE_CLASSNAME);\n for (const el of elements) el.classList.remove(ACTIVE_CLASSNAME);\n li.classList.remove(ACTIVE_CLASSNAME);\n } else {\n addActiveClassForId(itemId);\n }\n\n if (p.onItemClick) {\n const info: ItemClickInfo = {\n id: itemId,\n path: nodeRegistry.getPath(itemId),\n type: 'title',\n ...(item.data && { data: item.data }),\n };\n p.onItemClick(info);\n }\n };\n return (\n <li class={cn('title', item.disabled && 'menu-disabled', p.class?.itemWrap)} id={itemId}>\n <h4 class=\"menu-title\" onClick={handleTitleClick}>\n {item.content as Element}\n </h4>\n <ul>\n <For each={item.items}>{subItem => renderItems(subItem, itemId)}</For>\n </ul>\n </li>\n );\n }\n }\n const isLazyRoot = p.lazyItems !== undefined;\n const [rootItems, setRootItems] = createSignal<MenuItem[] | null>(\n isLazyRoot ? null : (p.items ?? []),\n );\n const [isRootLoading, setIsRootLoading] = createSignal(false);\n\n createEffect(\n on(\n () => p.items,\n items => {\n if (!isLazyRoot && items) {\n nodeRegistry.clear();\n lazyFolderRegistry.clear();\n setRootItems(items);\n }\n },\n { defer: true },\n ),\n );\n\n onCleanup(function clearMenuRegistries() {\n nodeRegistry.clear();\n lazyFolderRegistry.clear();\n });\n\n const loadRootItems = async () => {\n if (!p.lazyItems || rootItems() !== null || isRootLoading()) return;\n setIsRootLoading(true);\n try {\n const items = await p.lazyItems();\n setRootItems(items);\n } catch (e) {\n if (p.onError) {\n const errorInfo: MenuErrorInfo = {\n source: 'root',\n error: e,\n message: e instanceof Error ? e.message : 'Failed to load menu items',\n };\n p.onError(errorInfo);\n }\n } finally {\n setIsRootLoading(false);\n }\n };\n if (isLazyRoot) {\n loadRootItems();\n }\n const menuClass = createMemo(() =>\n cn(menuVariants({ size: p.size, direction: p.direction }), getColor(p.color), p.class?.root),\n );\n\n if (p.setMenuFunction) {\n p.setMenuFunction({\n focusById,\n collapseById,\n refreshById,\n refreshAll,\n collapseAll,\n expandedAll,\n });\n }\n return (\n <>\n <Show when={isRootLoading()}>\n <div class={cn(menuClass(), 'flex size-full justify-center p-4')}>\n <span class=\"loading loading-spinner loading-md m-auto\"></span>\n </div>\n </Show>\n <Show when={!isRootLoading()}>\n <Show\n when={rootItems() && rootItems()!.length > 0}\n fallback={\n <div class=\"text-base-content/50 flex flex-col items-center justify-center gap-2 p-4 text-center text-sm italic\">\n <span>No menu items available.</span>\n <Button\n icon={<RefreshCw size={10} />}\n variant={'default'}\n size={'4xs'}\n class=\"w-fit px-1.5\"\n onClick={loadRootItems}\n >\n Try again\n </Button>\n </div>\n }\n >\n <ul class={menuClass()} ref={ele => (ulRootRef = ele)} {...(p.id && { id: p.id })}>\n <For each={rootItems()!}>{item => renderItems(item)}</For>\n </ul>\n </Show>\n </Show>\n </>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"menu.js","names":["cn","getColor","cva","VariantProps","RefreshCw","Accessor","Component","createEffect","createMemo","createSignal","createUniqueId","For","JSXElement","mergeProps","on","onCleanup","onMount","Setter","Show","Button","FolderItem","ItemClickInfo","MenuErrorInfo","MenuItem","MenuProps","menuVariants","variants","size","xs","sm","md","lg","xl","direction","vertical","horizontal","MenuVariantsProps","NodeRegistry","parentMap","Map","register","id","parentId","set","getPath","path","currentId","unshift","get","has","clear","LazyFolderRegistry","refreshFns","refreshFn","unregister","delete","refresh","fn","refreshAll","forEach","LazyFolderContent","item","renderItems","shouldLoad","isLoading","setIsLoading","onLoadError","error","onRegisterRefresh","props","loadedItems","setLoadedItems","loadItems","force","lazyItems","items","e","defer","_$createComponent","when","children","each","subItem","ACTIVE_CLASSNAME","Menu","p","color","highlightActive","const","ulRootRef","HTMLUListElement","nodeRegistry","lazyFolderRegistry","addActiveClassForId","length","elements","Array","from","getElementsByClassName","el","classList","remove","nodeId","document","getElementById","add","expandPathToId","element","details","querySelector","HTMLDetailsElement","open","focusById","console","warn","collapseById","refreshById","collapseAll","detailsList","querySelectorAll","d","expandedAll","collapseOtherRootFolders","exceptId","rootFolders","li","parentElement","itemId","type","folderItem","defaultExpanded","isLazyFolder","undefined","setShouldLoad","detailsRef","handleToggle","Event","currentTarget","isExpanded","preventDefault","handleLoadError","onError","errorInfo","source","message","Error","handleFolderClick","MouseEvent","stopPropagation","disabled","currentIsExpanded","willExpand","setTimeout","onItemClick","info","data","_el$","_tmpl$2","_el$2","firstChild","_el$3","_el$5","nextSibling","_$setAttribute","addEventListener","_ref$","_$use","$$click","_$insert","content","Element","_tmpl$","fallback","_$effect","_p$","_v$","class","itemWrap","_v$2","_v$3","itemHeader","_$className","t","a","handleFileClick","_el$6","_tmpl$3","_el$7","handleTitleClick","contains","_el$8","_tmpl$4","_el$9","_el$0","isLazyRoot","rootItems","setRootItems","isRootLoading","setIsRootLoading","clearMenuRegistries","loadRootItems","menuClass","root","setMenuFunction","_el$1","_tmpl$5","_$memo","_el$11","_tmpl$7","_el$12","icon","variant","onClick","_el$10","_tmpl$6","ele","_$spread","_$mergeProps","_$delegateEvents"],"sources":["../../../src/components/menu/menu.tsx"],"sourcesContent":["import { cn } from '@/utils/cn';\r\nimport { getColor } from '@/utils/helper';\r\nimport { cva, type VariantProps } from 'class-variance-authority';\r\nimport RefreshCw from 'lucide-solid/icons/refresh-cw';\r\nimport {\r\n Accessor,\r\n Component,\r\n createEffect,\r\n createMemo,\r\n createSignal,\r\n createUniqueId,\r\n For,\r\n JSXElement,\r\n mergeProps,\r\n on,\r\n onCleanup,\r\n onMount,\r\n Setter,\r\n Show,\r\n} from 'solid-js';\r\nimport { Button } from '../button';\r\nimport type { FolderItem, ItemClickInfo, MenuErrorInfo, MenuItem, MenuProps } from './menu.types';\r\n\r\nconst menuVariants = cva('menu', {\r\n variants: {\r\n size: { xs: 'menu-xs', sm: 'menu-sm', md: 'menu-md', lg: 'menu-lg', xl: 'menu-xl' },\r\n direction: { vertical: 'menu-vertical', horizontal: 'menu-horizontal' },\r\n },\r\n});\r\n\r\nexport type MenuVariantsProps = VariantProps<typeof menuVariants>;\r\n\r\nclass NodeRegistry {\r\n private parentMap = new Map<string, string | null>();\r\n register(id: string, parentId: string | null) {\r\n this.parentMap.set(id, parentId);\r\n }\r\n getPath(id: string): string[] {\r\n const path: string[] = [];\r\n let currentId: string | null | undefined = id;\r\n while (currentId != null) {\r\n path.unshift(currentId);\r\n currentId = this.parentMap.get(currentId);\r\n }\r\n return path;\r\n }\r\n has(id: string): boolean {\r\n return this.parentMap.has(id);\r\n }\r\n clear() {\r\n this.parentMap.clear();\r\n }\r\n}\r\n\r\nclass LazyFolderRegistry {\r\n private refreshFns = new Map<string, () => void>();\r\n register(id: string, refreshFn: () => void) {\r\n this.refreshFns.set(id, refreshFn);\r\n }\r\n unregister(id: string) {\r\n this.refreshFns.delete(id);\r\n }\r\n refresh(id: string) {\r\n const fn = this.refreshFns.get(id);\r\n if (fn) fn();\r\n }\r\n refreshAll() {\r\n this.refreshFns.forEach(fn => fn());\r\n }\r\n has(id: string): boolean {\r\n return this.refreshFns.has(id);\r\n }\r\n clear() {\r\n this.refreshFns.clear();\r\n }\r\n}\r\n\r\nconst LazyFolderContent: Component<{\r\n item: FolderItem;\r\n renderItems: (item: MenuItem, parentId: string | null) => JSXElement;\r\n parentId: string | null;\r\n shouldLoad: Accessor<boolean>;\r\n isLoading: Accessor<boolean>;\r\n setIsLoading: Setter<boolean>;\r\n onLoadError: (error: unknown) => void;\r\n onRegisterRefresh: (refreshFn: () => void) => void;\r\n}> = props => {\r\n const [loadedItems, setLoadedItems] = createSignal<MenuItem[] | null>(null);\r\n const loadItems = async (force = false) => {\r\n if (props.isLoading()) return;\r\n if (loadedItems() !== null && !force) return;\r\n if (!props.item.lazyItems) return;\r\n props.setIsLoading(true);\r\n try {\r\n const items = await props.item.lazyItems();\r\n setLoadedItems(items);\r\n } catch (e) {\r\n props.onLoadError(e);\r\n } finally {\r\n props.setIsLoading(false);\r\n }\r\n };\r\n const refresh = () => {\r\n loadItems(true);\r\n };\r\n onMount(() => {\r\n props.onRegisterRefresh(refresh);\r\n });\r\n createEffect(\r\n on(\r\n () => props.shouldLoad(),\r\n shouldLoad => {\r\n if (shouldLoad && loadedItems() === null) {\r\n loadItems();\r\n }\r\n },\r\n { defer: true },\r\n ),\r\n );\r\n return (\r\n <Show when={loadedItems()}>\r\n <For each={loadedItems()!}>{subItem => props.renderItems(subItem, props.parentId)}</For>\r\n </Show>\r\n );\r\n};\r\n\r\nconst ACTIVE_CLASSNAME = '_6ca32a';\r\nexport const Menu: Component<MenuProps> = p => {\r\n p = mergeProps(\r\n { size: 'md', direction: 'vertical', color: 'secondary', highlightActive: true } as const,\r\n p,\r\n );\r\n let ulRootRef: HTMLUListElement;\r\n const nodeRegistry = new NodeRegistry();\r\n const lazyFolderRegistry = new LazyFolderRegistry();\r\n function addActiveClassForId(id: string) {\r\n if (!ulRootRef || !p.highlightActive) return;\r\n const path = nodeRegistry.getPath(id);\r\n if (path.length === 0) return;\r\n\r\n const elements = Array.from(ulRootRef.getElementsByClassName(ACTIVE_CLASSNAME));\r\n\r\n for (const el of elements) el.classList.remove(ACTIVE_CLASSNAME);\r\n for (const nodeId of path) document.getElementById(nodeId)?.classList?.add(ACTIVE_CLASSNAME);\r\n }\r\n function expandPathToId(id: string) {\r\n const path = nodeRegistry.getPath(id);\r\n for (const nodeId of path) {\r\n const element = document.getElementById(nodeId);\r\n if (!element) continue;\r\n const details = element.querySelector(':scope > details') as HTMLDetailsElement | null;\r\n if (details && !details.open) {\r\n details.open = true;\r\n }\r\n }\r\n }\r\n function focusById(id: string) {\r\n if (!nodeRegistry.has(id)) {\r\n console.warn(`Menu.focusById: Node with id \"${id}\" not found in registry`);\r\n return;\r\n }\r\n expandPathToId(id);\r\n addActiveClassForId(id);\r\n }\r\n function collapseById(id: string) {\r\n const element = document.getElementById(id);\r\n if (!element) {\r\n console.warn(`Menu.collapseById: Element with id \"${id}\" not found`);\r\n return;\r\n }\r\n const details = element.querySelector(':scope > details') as HTMLDetailsElement | null;\r\n if (details) {\r\n details.open = false;\r\n const elements = details.getElementsByClassName(ACTIVE_CLASSNAME);\r\n for (const el of elements) el.classList.remove(ACTIVE_CLASSNAME);\r\n element.classList.remove(ACTIVE_CLASSNAME);\r\n }\r\n }\r\n function refreshById(id: string) {\r\n if (!lazyFolderRegistry.has(id)) {\r\n console.warn(`Menu.refreshById: Lazy folder with id \"${id}\" not found`);\r\n return;\r\n }\r\n lazyFolderRegistry.refresh(id);\r\n }\r\n function refreshAll() {\r\n lazyFolderRegistry.refreshAll();\r\n }\r\n function collapseAll() {\r\n if (!ulRootRef) return;\r\n const detailsList = ulRootRef.querySelectorAll('details');\r\n detailsList.forEach(d => (d.open = false));\r\n }\r\n function expandedAll() {\r\n if (!ulRootRef) return;\r\n const detailsList = ulRootRef.querySelectorAll('details');\r\n detailsList.forEach(d => (d.open = true));\r\n }\r\n function collapseOtherRootFolders(exceptId: string) {\r\n if (!ulRootRef) return;\r\n // Only collapse direct children (level 1 folders)\r\n const rootFolders = ulRootRef.querySelectorAll(':scope > li.folder > details');\r\n rootFolders.forEach(details => {\r\n const li = details.parentElement;\r\n if (li && li.id !== exceptId && (details as HTMLDetailsElement).open) {\r\n (details as HTMLDetailsElement).open = false;\r\n }\r\n });\r\n }\r\n function renderItems(item: MenuItem, parentId: string | null = null) {\r\n const itemId = item.id ?? createUniqueId();\r\n nodeRegistry.register(itemId, parentId);\r\n\r\n if (item.type === 'folder') {\r\n const folderItem = mergeProps(\r\n { defaultExpanded: item.defaultExpanded ?? p.defaultExpanded ?? false },\r\n item,\r\n { id: itemId },\r\n );\r\n const isLazyFolder = folderItem.lazyItems !== undefined;\r\n const [shouldLoad, setShouldLoad] = createSignal(folderItem.defaultExpanded);\r\n const [isLoading, setIsLoading] = createSignal(false);\r\n let detailsRef: HTMLDetailsElement | undefined;\r\n\r\n const handleToggle = (e: Event) => {\r\n const details = e.currentTarget as HTMLDetailsElement;\r\n const isExpanded = details.open;\r\n if (isLoading()) {\r\n e.preventDefault();\r\n return;\r\n }\r\n if (isLazyFolder) {\r\n setShouldLoad(isExpanded);\r\n }\r\n };\r\n\r\n const handleLoadError = (error: unknown) => {\r\n if (detailsRef) {\r\n detailsRef.open = false;\r\n }\r\n setShouldLoad(false);\r\n if (p.onError) {\r\n const errorInfo: MenuErrorInfo = {\r\n source: 'folder',\r\n itemId,\r\n path: nodeRegistry.getPath(itemId),\r\n error,\r\n message: error instanceof Error ? error.message : 'Failed to load folder items',\r\n };\r\n p.onError(errorInfo);\r\n }\r\n };\r\n\r\n const handleFolderClick = (e: MouseEvent) => {\r\n e.stopPropagation();\r\n if (isLoading() || item.disabled) {\r\n e.preventDefault();\r\n return;\r\n }\r\n\r\n const currentIsExpanded = detailsRef?.open ?? folderItem.defaultExpanded;\r\n const willExpand = !currentIsExpanded;\r\n\r\n // In horizontal mode, collapse other root folders when expanding a root folder\r\n if (p.direction === 'horizontal' && parentId === null && willExpand) {\r\n collapseOtherRootFolders(itemId);\r\n }\r\n\r\n if (detailsRef?.open === false) {\r\n addActiveClassForId(itemId);\r\n } else {\r\n setTimeout(() => {\r\n collapseById(itemId);\r\n });\r\n }\r\n\r\n if (p.onItemClick) {\r\n const isExpanded = willExpand;\r\n const info: ItemClickInfo = {\r\n id: itemId,\r\n path: nodeRegistry.getPath(itemId),\r\n type: 'folder',\r\n isExpanded,\r\n data: item.data,\r\n };\r\n p.onItemClick(info);\r\n }\r\n };\r\n return (\r\n <li\r\n class={cn(\r\n 'folder',\r\n (folderItem.disabled || isLoading()) && 'menu-disabled',\r\n p.class?.itemWrap,\r\n )}\r\n id={itemId}\r\n >\r\n <details ref={detailsRef} open={folderItem.defaultExpanded} onToggle={handleToggle}>\r\n <summary\r\n class={cn(isLoading() && 'after:hidden', p.class?.itemHeader)}\r\n onClick={handleFolderClick}\r\n >\r\n {folderItem.content as Element}\r\n <Show when={isLoading()}>\r\n <span class=\"loading loading-spinner loading-xs\"></span>\r\n </Show>\r\n </summary>\r\n <ul>\r\n <Show\r\n when={isLazyFolder}\r\n fallback={\r\n <For each={(folderItem as { items: MenuItem[] }).items}>\r\n {subItem => renderItems(subItem, itemId)}\r\n </For>\r\n }\r\n >\r\n <LazyFolderContent\r\n {...{\r\n renderItems,\r\n shouldLoad,\r\n isLoading,\r\n setIsLoading,\r\n item: folderItem,\r\n parentId: itemId,\r\n onLoadError: handleLoadError,\r\n onRegisterRefresh: refreshFn => lazyFolderRegistry.register(itemId, refreshFn),\r\n }}\r\n />\r\n </Show>\r\n </ul>\r\n </details>\r\n </li>\r\n );\r\n }\r\n if (item.type === 'file') {\r\n const handleFileClick = (e: MouseEvent) => {\r\n e.stopPropagation();\r\n addActiveClassForId(itemId);\r\n\r\n if (p.onItemClick) {\r\n const info: ItemClickInfo = {\r\n id: itemId,\r\n path: nodeRegistry.getPath(itemId),\r\n type: 'file',\r\n ...(item.data && { data: item.data }),\r\n };\r\n p.onItemClick(info);\r\n }\r\n };\r\n return (\r\n <li\r\n class={cn('file', item.disabled && 'menu-disabled', p.class?.itemWrap)}\r\n id={itemId}\r\n tabindex=\"0\"\r\n onClick={handleFileClick}\r\n >\r\n <div>{item.content as Element}</div>\r\n </li>\r\n );\r\n }\r\n if (item.type === 'title') {\r\n const handleTitleClick = (e: MouseEvent) => {\r\n e.stopPropagation();\r\n\r\n const li = document.getElementById(itemId);\r\n if (li && li.classList.contains(ACTIVE_CLASSNAME)) {\r\n const elements = li.getElementsByClassName(ACTIVE_CLASSNAME);\r\n for (const el of elements) el.classList.remove(ACTIVE_CLASSNAME);\r\n li.classList.remove(ACTIVE_CLASSNAME);\r\n } else {\r\n addActiveClassForId(itemId);\r\n }\r\n\r\n if (p.onItemClick) {\r\n const info: ItemClickInfo = {\r\n id: itemId,\r\n path: nodeRegistry.getPath(itemId),\r\n type: 'title',\r\n ...(item.data && { data: item.data }),\r\n };\r\n p.onItemClick(info);\r\n }\r\n };\r\n return (\r\n <li class={cn('title', item.disabled && 'menu-disabled', p.class?.itemWrap)} id={itemId}>\r\n <h4 class=\"menu-title\" onClick={handleTitleClick}>\r\n {item.content as Element}\r\n </h4>\r\n <ul>\r\n <For each={item.items}>{subItem => renderItems(subItem, itemId)}</For>\r\n </ul>\r\n </li>\r\n );\r\n }\r\n }\r\n const isLazyRoot = p.lazyItems !== undefined;\r\n const [rootItems, setRootItems] = createSignal<MenuItem[] | null>(\r\n isLazyRoot ? null : (p.items ?? []),\r\n );\r\n const [isRootLoading, setIsRootLoading] = createSignal(false);\r\n\r\n createEffect(\r\n on(\r\n () => p.items,\r\n items => {\r\n if (!isLazyRoot && items) {\r\n nodeRegistry.clear();\r\n lazyFolderRegistry.clear();\r\n setRootItems(items);\r\n }\r\n },\r\n { defer: true },\r\n ),\r\n );\r\n\r\n onCleanup(function clearMenuRegistries() {\r\n nodeRegistry.clear();\r\n lazyFolderRegistry.clear();\r\n });\r\n\r\n const loadRootItems = async () => {\r\n if (!p.lazyItems || rootItems() !== null || isRootLoading()) return;\r\n setIsRootLoading(true);\r\n try {\r\n const items = await p.lazyItems();\r\n setRootItems(items);\r\n } catch (e) {\r\n if (p.onError) {\r\n const errorInfo: MenuErrorInfo = {\r\n source: 'root',\r\n error: e,\r\n message: e instanceof Error ? e.message : 'Failed to load menu items',\r\n };\r\n p.onError(errorInfo);\r\n }\r\n } finally {\r\n setIsRootLoading(false);\r\n }\r\n };\r\n if (isLazyRoot) {\r\n loadRootItems();\r\n }\r\n const menuClass = createMemo(() =>\r\n cn(menuVariants({ size: p.size, direction: p.direction }), getColor(p.color), p.class?.root),\r\n );\r\n\r\n if (p.setMenuFunction) {\r\n p.setMenuFunction({\r\n focusById,\r\n collapseById,\r\n refreshById,\r\n refreshAll,\r\n collapseAll,\r\n expandedAll,\r\n });\r\n }\r\n return (\r\n <>\r\n <Show when={isRootLoading()}>\r\n <div class={cn(menuClass(), 'flex size-full justify-center p-4')}>\r\n <span class=\"loading loading-spinner loading-md m-auto\"></span>\r\n </div>\r\n </Show>\r\n <Show when={!isRootLoading()}>\r\n <Show\r\n when={rootItems() && rootItems()!.length > 0}\r\n fallback={\r\n <div class=\"text-base-content/50 flex flex-col items-center justify-center gap-2 p-4 text-center text-sm italic\">\r\n <span>No menu items available.</span>\r\n <Button\r\n icon={<RefreshCw size={10} />}\r\n variant={'default'}\r\n size={'4xs'}\r\n class=\"w-fit px-1.5\"\r\n onClick={loadRootItems}\r\n >\r\n Try again\r\n </Button>\r\n </div>\r\n }\r\n >\r\n <ul class={menuClass()} ref={ele => (ulRootRef = ele)} {...(p.id && { id: p.id })}>\r\n <For each={rootItems()!}>{item => renderItems(item)}</For>\r\n </ul>\r\n </Show>\r\n </Show>\r\n </>\r\n );\r\n};\r\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal.js","names":["SolidComponent","cn","AnimationConfig","renderCSSAnimation","conditionalRender","X","Component","createEffect","createSignal","createUniqueId","mergeProps","on","onCleanup","Show","ZIndex","ZIndexType","ModalType","onClose","width","closeOnOutsideClick","closeOnEsc","closable","header","body","footer","open","mask","enabled","blur","class","Partial","Record","preRender","animate","Omit","name","AnimateType","TRANSFORM_ANIMATIONS","Set","modalIds","setModalIds","popModalId","newArr","slice","pop","modalCloseCallbacks","Map","globalKeyDownHandler","e","KeyboardEvent","key","topId","at","get","registerModalCallback","id","cb","size","document","addEventListener","set","unregisterModalCallback","delete","removeEventListener","ComponentModal","p","duration","modalId","unregisterModal","renderMaskEnabled","renderMaskClass","animName","isTransformAnim","has","renderModalBoxAnim","animation","renderOverlayAnim","renderBoxStyle","style","overlayDone","setOverlayDone","handleOverlayAnimEnd","boxVisible","handleBackdropClick","_$createComponent","type","MODAL","blockScroll","position","inset","wrapper","children","when","_el$","_tmpl$","$$click","_$effect","_$className","_$memo","_el$2","_tmpl$2","_el$3","_tmpl$4","_el$5","firstChild","_el$6","_el$7","nextSibling","stopPropagation","_$insert","_el$4","_tmpl$3","_p$","_v$","modal","_v$2","t","_$style","undefined","_c$","_el$9","_tmpl$5","_$addEventListener","closeButton","fallback","_el$0","_tmpl$6","_el$1","Element","_el$8","_v$3","_v$4","visibility","_v$5","_v$6","a","o","Modal","_$delegateEvents"],"sources":["../../../src/components/modal/modal.tsx"],"sourcesContent":["import { SolidComponent } from '@/type';\nimport { cn } from '@/utils/cn';\nimport { AnimationConfig, renderCSSAnimation } from '@/utils/helper';\nimport { conditionalRender } from '@/utils/hoc';\nimport X from 'lucide-solid/icons/x';\n\nimport {\n Component,\n createEffect,\n createSignal,\n createUniqueId,\n mergeProps,\n on,\n onCleanup,\n Show,\n} from 'solid-js';\nimport { ZIndex, ZIndexType } from '../z-index';\n\nexport type ModalType = {\n onClose: () => void;\n width?: string;\n closeOnOutsideClick?: boolean;\n closeOnEsc?: boolean;\n closable?: boolean;\n header?: SolidComponent;\n body?: SolidComponent;\n footer?: SolidComponent;\n open?: boolean;\n mask?: boolean | { enabled: boolean; blur: boolean };\n class?: Partial<\n Record<'wrapper' | 'modal' | 'header' | 'body' | 'footer' | 'closeButton', string>\n >;\n preRender?: boolean;\n animate?: Omit<AnimationConfig, 'name'> & {\n name: AnimateType;\n };\n};\n\n// Only opacity-based animations are safe to use on the modal box directly\n// because transform-based animations create a new containing block for\n// position:fixed descendants, which breaks fixed positioning inside body slots.\n// Transform animations are applied on a sibling overlay div instead.\ntype AnimateType =\n | 'none'\n | 'lightSpeedInRight'\n | 'lightSpeedInLeft'\n | 'fadeIn'\n | 'fadeInLeft'\n | 'fadeInRight'\n | 'fadeInDown'\n | 'fadeInUp'\n | 'bounceIn'\n | 'scaleInCenter'\n | 'slideInFwdCenter'\n | 'slideInBck'\n | 'tiltIn'\n | 'swingInRightBck'\n | 'puffInCenter'\n | 'scaleInBl';\n\n// Animations that use transform in their keyframes — these create a containing\n// block for position:fixed elements during the animation. They must NOT be\n// placed on any ancestor of body content.\nconst TRANSFORM_ANIMATIONS = new Set<AnimateType>([\n 'lightSpeedInRight',\n 'lightSpeedInLeft',\n 'fadeInLeft',\n 'fadeInRight',\n 'fadeInDown',\n 'fadeInUp',\n 'bounceIn',\n 'scaleInCenter',\n 'slideInFwdCenter',\n 'slideInBck',\n 'tiltIn',\n 'swingInRightBck',\n 'puffInCenter',\n 'scaleInBl',\n]);\n\n// Track active modals for overlay logic (only topmost modal shows mask)\nconst [modalIds, setModalIds] = createSignal<string[]>([]);\nfunction popModalId() {\n const newArr = modalIds().slice();\n newArr.pop();\n setModalIds(newArr);\n}\n\n// Global ESC key handler — single listener shared across all modal instances\nconst modalCloseCallbacks = new Map<string, () => void>();\n\nfunction globalKeyDownHandler(e: KeyboardEvent) {\n if (e.key !== 'Escape') return;\n const topId = modalIds().at(-1);\n if (topId) modalCloseCallbacks.get(topId)?.();\n}\n\nfunction registerModalCallback(id: string, cb: () => void) {\n if (modalCloseCallbacks.size === 0) {\n document.addEventListener('keydown', globalKeyDownHandler);\n }\n modalCloseCallbacks.set(id, cb);\n}\n\nfunction unregisterModalCallback(id: string) {\n modalCloseCallbacks.delete(id);\n if (modalCloseCallbacks.size === 0) {\n document.removeEventListener('keydown', globalKeyDownHandler);\n }\n}\n\nconst ComponentModal: Component<ModalType> = p => {\n p = mergeProps(\n {\n closeOnOutsideClick: true,\n closeOnEsc: true,\n open: true,\n onClose: () => {},\n closable: true,\n preRender: false,\n animate: {\n name: 'puffInCenter',\n duration: '300ms',\n },\n mask: true,\n } as ModalType,\n p,\n );\n\n const modalId = createUniqueId();\n\n onCleanup(function unregisterModal() {\n unregisterModalCallback(modalId);\n if (modalId === modalIds().at(-1)) {\n popModalId();\n }\n });\n\n // Manage modalIds stack for overlay logic\n createEffect(\n on(\n () => p.open,\n open => {\n if (open) {\n if (modalId !== modalIds().at(-1)) {\n setModalIds([...modalIds(), modalId]);\n }\n registerModalCallback(modalId, () => {\n if (p.closeOnEsc) p.onClose();\n });\n } else {\n unregisterModalCallback(modalId);\n if (modalId === modalIds().at(-1)) {\n popModalId();\n }\n }\n },\n ),\n );\n\n const renderMaskEnabled = (): boolean => {\n if (!p.open) return false;\n if (modalId !== modalIds().at(-1)) return false;\n if (p.mask === false) return false;\n if (typeof p.mask === 'object' && p.mask?.enabled === false) return false;\n return true;\n };\n\n const renderMaskClass = (): string => {\n if (typeof p.mask === 'object' && p.mask?.blur === false) {\n return 'bg-modal-overlay';\n }\n return 'bg-modal-overlay backdrop-blur-[5px]';\n };\n\n const animName = (): AnimateType => p.animate?.name ?? 'none';\n const isTransformAnim = () => TRANSFORM_ANIMATIONS.has(animName());\n\n // For transform-based animations: rendered on a sibling absolutely-positioned\n // overlay div that visually matches the modal box but is NOT an ancestor of\n // body content. This completely avoids the containing-block issue.\n // For opacity-only animations (fadeIn): applied directly on the modal box.\n const renderModalBoxAnim = () => {\n if (!isTransformAnim() && animName() !== 'none') {\n return { animation: renderCSSAnimation(p.animate!) };\n }\n return {};\n };\n\n const renderOverlayAnim = () => {\n if (isTransformAnim()) {\n return { animation: renderCSSAnimation(p.animate!) };\n }\n return {};\n };\n\n const renderBoxStyle = () => {\n const style: Record<string, any> = {};\n if (p.width) {\n style['width'] = p.width;\n style['min-width'] = p.width;\n }\n return style;\n };\n\n // Overlay: a visually identical copy of the modal box that carries the\n // transform animation. It sits on top of the real modal box via absolute\n // positioning. Once animation ends it is hidden and the real box is shown.\n const [overlayDone, setOverlayDone] = createSignal(false);\n const handleOverlayAnimEnd = () => setOverlayDone(true);\n\n // Reset overlayDone each time modal re-opens so transform animation replays.\n createEffect(\n on(\n () => p.open,\n open => {\n if (open) setOverlayDone(false);\n },\n ),\n );\n\n // Real modal box becomes visible only after transform animation finishes\n // (to avoid showing both simultaneously).\n const boxVisible = () => !isTransformAnim() || overlayDone();\n\n const handleBackdropClick = () => {\n if (p.closeOnOutsideClick) {\n p.onClose();\n }\n };\n\n return (\n <ZIndex\n type={ZIndexType.MODAL}\n open={p.open ?? false}\n blockScroll\n preRender={p.preRender}\n position={{ inset: '0' }}\n class={cn('mo01', p.class?.wrapper)}\n >\n {/* Backdrop overlay — only for topmost modal */}\n <Show when={renderMaskEnabled()}>\n <div class={cn('mo02', renderMaskClass())} onClick={handleBackdropClick} />\n </Show>\n\n {/* Invisible hit area for outside-click when mask is disabled */}\n <Show when={!renderMaskEnabled() && p.closeOnOutsideClick}>\n <div class=\"mo02\" onClick={handleBackdropClick} />\n </Show>\n\n {/* Wrapper: flex item căn giữa bởi parent. Kích thước khớp real box.\n Overlay absolute bên trong → luôn cùng vị trí & kích thước với real box. */}\n <div class=\"mo03\" onClick={e => e.stopPropagation()}>\n {/* === Transform animation approach ===\n Overlay là visual clone với animation transform, positioned absolute\n bên trong wrapper → khớp 100% kích thước/vị trí với real box.\n Giữ body content thoát khỏi transform ancestor. */}\n <Show when={isTransformAnim() && !overlayDone()}>\n <div\n class={cn('mo04', p.class?.modal)}\n style={{ ...renderBoxStyle(), ...renderOverlayAnim() }}\n onAnimationEnd={handleOverlayAnimEnd}\n aria-hidden=\"true\"\n />\n </Show>\n\n {/* === Real modal box ===\n Dùng opacity animation (an toàn) hoặc không animation.\n Body content luôn thoát khỏi transform ancestor. */}\n <div\n class={cn('mo05', p.class?.modal)}\n style={{\n ...renderModalBoxAnim(),\n ...renderBoxStyle(),\n visibility: boxVisible() ? 'visible' : 'hidden',\n }}\n >\n {p.closable && (\n <button class={cn('mo06', p.class?.closeButton)} onClick={p.onClose} aria-label=\"Close\">\n <X size={16} />\n </button>\n )}\n\n <div class={cn('mo-header', p.class?.header)}>\n <Show when={p.header} fallback={<div class=\"mo07\">Modal ID: {modalId}</div>}>\n {p.header as Element}\n </Show>\n </div>\n\n <div class={cn('mo08', p.class?.body)}>\n <Show when={p.body}>{p.body as Element}</Show>\n </div>\n\n <Show when={p.footer}>\n <div class={cn('mo-footer', p.class?.footer)}>{p.footer as Element}</div>\n </Show>\n </div>\n </div>\n </ZIndex>\n );\n};\n\nexport const Modal = conditionalRender(ComponentModal, { preRender: 'preRender', when: 'open' });\n\nexport { ComponentModal };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"modal.js","names":["SolidComponent","cn","AnimationConfig","renderCSSAnimation","conditionalRender","X","Component","createEffect","createSignal","createUniqueId","mergeProps","on","onCleanup","Show","ZIndex","ZIndexType","ModalType","onClose","width","closeOnOutsideClick","closeOnEsc","closable","header","body","footer","open","mask","enabled","blur","class","Partial","Record","preRender","animate","Omit","name","AnimateType","TRANSFORM_ANIMATIONS","Set","modalIds","setModalIds","popModalId","newArr","slice","pop","modalCloseCallbacks","Map","globalKeyDownHandler","e","KeyboardEvent","key","topId","at","get","registerModalCallback","id","cb","size","document","addEventListener","set","unregisterModalCallback","delete","removeEventListener","ComponentModal","p","duration","modalId","unregisterModal","renderMaskEnabled","renderMaskClass","animName","isTransformAnim","has","renderModalBoxAnim","animation","renderOverlayAnim","renderBoxStyle","style","overlayDone","setOverlayDone","handleOverlayAnimEnd","boxVisible","handleBackdropClick","_$createComponent","type","MODAL","blockScroll","position","inset","wrapper","children","when","_el$","_tmpl$","$$click","_$effect","_$className","_$memo","_el$2","_tmpl$2","_el$3","_tmpl$4","_el$5","firstChild","_el$6","_el$7","nextSibling","stopPropagation","_$insert","_el$4","_tmpl$3","_p$","_v$","modal","_v$2","t","_$style","undefined","_c$","_el$9","_tmpl$5","_$addEventListener","closeButton","fallback","_el$0","_tmpl$6","_el$1","Element","_el$8","_v$3","_v$4","visibility","_v$5","_v$6","a","o","Modal","_$delegateEvents"],"sources":["../../../src/components/modal/modal.tsx"],"sourcesContent":["import { SolidComponent } from '@/type';\r\nimport { cn } from '@/utils/cn';\r\nimport { AnimationConfig, renderCSSAnimation } from '@/utils/helper';\r\nimport { conditionalRender } from '@/utils/hoc';\r\nimport X from 'lucide-solid/icons/x';\r\n\r\nimport {\r\n Component,\r\n createEffect,\r\n createSignal,\r\n createUniqueId,\r\n mergeProps,\r\n on,\r\n onCleanup,\r\n Show,\r\n} from 'solid-js';\r\nimport { ZIndex, ZIndexType } from '../z-index';\r\n\r\nexport type ModalType = {\r\n onClose: () => void;\r\n width?: string;\r\n closeOnOutsideClick?: boolean;\r\n closeOnEsc?: boolean;\r\n closable?: boolean;\r\n header?: SolidComponent;\r\n body?: SolidComponent;\r\n footer?: SolidComponent;\r\n open?: boolean;\r\n mask?: boolean | { enabled: boolean; blur: boolean };\r\n class?: Partial<\r\n Record<'wrapper' | 'modal' | 'header' | 'body' | 'footer' | 'closeButton', string>\r\n >;\r\n preRender?: boolean;\r\n animate?: Omit<AnimationConfig, 'name'> & {\r\n name: AnimateType;\r\n };\r\n};\r\n\r\n// Only opacity-based animations are safe to use on the modal box directly\r\n// because transform-based animations create a new containing block for\r\n// position:fixed descendants, which breaks fixed positioning inside body slots.\r\n// Transform animations are applied on a sibling overlay div instead.\r\ntype AnimateType =\r\n | 'none'\r\n | 'lightSpeedInRight'\r\n | 'lightSpeedInLeft'\r\n | 'fadeIn'\r\n | 'fadeInLeft'\r\n | 'fadeInRight'\r\n | 'fadeInDown'\r\n | 'fadeInUp'\r\n | 'bounceIn'\r\n | 'scaleInCenter'\r\n | 'slideInFwdCenter'\r\n | 'slideInBck'\r\n | 'tiltIn'\r\n | 'swingInRightBck'\r\n | 'puffInCenter'\r\n | 'scaleInBl';\r\n\r\n// Animations that use transform in their keyframes — these create a containing\r\n// block for position:fixed elements during the animation. They must NOT be\r\n// placed on any ancestor of body content.\r\nconst TRANSFORM_ANIMATIONS = new Set<AnimateType>([\r\n 'lightSpeedInRight',\r\n 'lightSpeedInLeft',\r\n 'fadeInLeft',\r\n 'fadeInRight',\r\n 'fadeInDown',\r\n 'fadeInUp',\r\n 'bounceIn',\r\n 'scaleInCenter',\r\n 'slideInFwdCenter',\r\n 'slideInBck',\r\n 'tiltIn',\r\n 'swingInRightBck',\r\n 'puffInCenter',\r\n 'scaleInBl',\r\n]);\r\n\r\n// Track active modals for overlay logic (only topmost modal shows mask)\r\nconst [modalIds, setModalIds] = createSignal<string[]>([]);\r\nfunction popModalId() {\r\n const newArr = modalIds().slice();\r\n newArr.pop();\r\n setModalIds(newArr);\r\n}\r\n\r\n// Global ESC key handler — single listener shared across all modal instances\r\nconst modalCloseCallbacks = new Map<string, () => void>();\r\n\r\nfunction globalKeyDownHandler(e: KeyboardEvent) {\r\n if (e.key !== 'Escape') return;\r\n const topId = modalIds().at(-1);\r\n if (topId) modalCloseCallbacks.get(topId)?.();\r\n}\r\n\r\nfunction registerModalCallback(id: string, cb: () => void) {\r\n if (modalCloseCallbacks.size === 0) {\r\n document.addEventListener('keydown', globalKeyDownHandler);\r\n }\r\n modalCloseCallbacks.set(id, cb);\r\n}\r\n\r\nfunction unregisterModalCallback(id: string) {\r\n modalCloseCallbacks.delete(id);\r\n if (modalCloseCallbacks.size === 0) {\r\n document.removeEventListener('keydown', globalKeyDownHandler);\r\n }\r\n}\r\n\r\nconst ComponentModal: Component<ModalType> = p => {\r\n p = mergeProps(\r\n {\r\n closeOnOutsideClick: true,\r\n closeOnEsc: true,\r\n open: true,\r\n onClose: () => {},\r\n closable: true,\r\n preRender: false,\r\n animate: {\r\n name: 'puffInCenter',\r\n duration: '300ms',\r\n },\r\n mask: true,\r\n } as ModalType,\r\n p,\r\n );\r\n\r\n const modalId = createUniqueId();\r\n\r\n onCleanup(function unregisterModal() {\r\n unregisterModalCallback(modalId);\r\n if (modalId === modalIds().at(-1)) {\r\n popModalId();\r\n }\r\n });\r\n\r\n // Manage modalIds stack for overlay logic\r\n createEffect(\r\n on(\r\n () => p.open,\r\n open => {\r\n if (open) {\r\n if (modalId !== modalIds().at(-1)) {\r\n setModalIds([...modalIds(), modalId]);\r\n }\r\n registerModalCallback(modalId, () => {\r\n if (p.closeOnEsc) p.onClose();\r\n });\r\n } else {\r\n unregisterModalCallback(modalId);\r\n if (modalId === modalIds().at(-1)) {\r\n popModalId();\r\n }\r\n }\r\n },\r\n ),\r\n );\r\n\r\n const renderMaskEnabled = (): boolean => {\r\n if (!p.open) return false;\r\n if (modalId !== modalIds().at(-1)) return false;\r\n if (p.mask === false) return false;\r\n if (typeof p.mask === 'object' && p.mask?.enabled === false) return false;\r\n return true;\r\n };\r\n\r\n const renderMaskClass = (): string => {\r\n if (typeof p.mask === 'object' && p.mask?.blur === false) {\r\n return 'bg-modal-overlay';\r\n }\r\n return 'bg-modal-overlay backdrop-blur-[5px]';\r\n };\r\n\r\n const animName = (): AnimateType => p.animate?.name ?? 'none';\r\n const isTransformAnim = () => TRANSFORM_ANIMATIONS.has(animName());\r\n\r\n // For transform-based animations: rendered on a sibling absolutely-positioned\r\n // overlay div that visually matches the modal box but is NOT an ancestor of\r\n // body content. This completely avoids the containing-block issue.\r\n // For opacity-only animations (fadeIn): applied directly on the modal box.\r\n const renderModalBoxAnim = () => {\r\n if (!isTransformAnim() && animName() !== 'none') {\r\n return { animation: renderCSSAnimation(p.animate!) };\r\n }\r\n return {};\r\n };\r\n\r\n const renderOverlayAnim = () => {\r\n if (isTransformAnim()) {\r\n return { animation: renderCSSAnimation(p.animate!) };\r\n }\r\n return {};\r\n };\r\n\r\n const renderBoxStyle = () => {\r\n const style: Record<string, any> = {};\r\n if (p.width) {\r\n style['width'] = p.width;\r\n style['min-width'] = p.width;\r\n }\r\n return style;\r\n };\r\n\r\n // Overlay: a visually identical copy of the modal box that carries the\r\n // transform animation. It sits on top of the real modal box via absolute\r\n // positioning. Once animation ends it is hidden and the real box is shown.\r\n const [overlayDone, setOverlayDone] = createSignal(false);\r\n const handleOverlayAnimEnd = () => setOverlayDone(true);\r\n\r\n // Reset overlayDone each time modal re-opens so transform animation replays.\r\n createEffect(\r\n on(\r\n () => p.open,\r\n open => {\r\n if (open) setOverlayDone(false);\r\n },\r\n ),\r\n );\r\n\r\n // Real modal box becomes visible only after transform animation finishes\r\n // (to avoid showing both simultaneously).\r\n const boxVisible = () => !isTransformAnim() || overlayDone();\r\n\r\n const handleBackdropClick = () => {\r\n if (p.closeOnOutsideClick) {\r\n p.onClose();\r\n }\r\n };\r\n\r\n return (\r\n <ZIndex\r\n type={ZIndexType.MODAL}\r\n open={p.open ?? false}\r\n blockScroll\r\n preRender={p.preRender}\r\n position={{ inset: '0' }}\r\n class={cn('mo01', p.class?.wrapper)}\r\n >\r\n {/* Backdrop overlay — only for topmost modal */}\r\n <Show when={renderMaskEnabled()}>\r\n <div class={cn('mo02', renderMaskClass())} onClick={handleBackdropClick} />\r\n </Show>\r\n\r\n {/* Invisible hit area for outside-click when mask is disabled */}\r\n <Show when={!renderMaskEnabled() && p.closeOnOutsideClick}>\r\n <div class=\"mo02\" onClick={handleBackdropClick} />\r\n </Show>\r\n\r\n {/* Wrapper: flex item căn giữa bởi parent. Kích thước khớp real box.\r\n Overlay absolute bên trong → luôn cùng vị trí & kích thước với real box. */}\r\n <div class=\"mo03\" onClick={e => e.stopPropagation()}>\r\n {/* === Transform animation approach ===\r\n Overlay là visual clone với animation transform, positioned absolute\r\n bên trong wrapper → khớp 100% kích thước/vị trí với real box.\r\n Giữ body content thoát khỏi transform ancestor. */}\r\n <Show when={isTransformAnim() && !overlayDone()}>\r\n <div\r\n class={cn('mo04', p.class?.modal)}\r\n style={{ ...renderBoxStyle(), ...renderOverlayAnim() }}\r\n onAnimationEnd={handleOverlayAnimEnd}\r\n aria-hidden=\"true\"\r\n />\r\n </Show>\r\n\r\n {/* === Real modal box ===\r\n Dùng opacity animation (an toàn) hoặc không animation.\r\n Body content luôn thoát khỏi transform ancestor. */}\r\n <div\r\n class={cn('mo05', p.class?.modal)}\r\n style={{\r\n ...renderModalBoxAnim(),\r\n ...renderBoxStyle(),\r\n visibility: boxVisible() ? 'visible' : 'hidden',\r\n }}\r\n >\r\n {p.closable && (\r\n <button class={cn('mo06', p.class?.closeButton)} onClick={p.onClose} aria-label=\"Close\">\r\n <X size={16} />\r\n </button>\r\n )}\r\n\r\n <div class={cn('mo-header', p.class?.header)}>\r\n <Show when={p.header} fallback={<div class=\"mo07\">Modal ID: {modalId}</div>}>\r\n {p.header as Element}\r\n </Show>\r\n </div>\r\n\r\n <div class={cn('mo08', p.class?.body)}>\r\n <Show when={p.body}>{p.body as Element}</Show>\r\n </div>\r\n\r\n <Show when={p.footer}>\r\n <div class={cn('mo-footer', p.class?.footer)}>{p.footer as Element}</div>\r\n </Show>\r\n </div>\r\n </div>\r\n </ZIndex>\r\n );\r\n};\r\n\r\nexport const Modal = conditionalRender(ComponentModal, { preRender: 'preRender', when: 'open' });\r\n\r\nexport { ComponentModal };\r\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modalContext.js","names":["createComponent","createRoot","createSignal","ComponentModal","ModalType","activeModalInstances","ModalInstance","destroy","createModal","options","Omit","disposeRoot","setIsOpen","v","disposed","doClose","callOnClose","onClose","index","indexOf","instance","splice","setTimeout","root","isOpen","_setIsOpen","open","preRender","push","closeAllModals","instances","forEach"],"sources":["../../../src/components/modal/modalContext.tsx"],"sourcesContent":["import { createComponent, createRoot, createSignal } from 'solid-js';\nimport { ComponentModal, ModalType } from './modal';\n\nconst activeModalInstances: ModalInstance[] = [];\n\ntype ModalInstance = {\n destroy: () => void;\n};\n\nexport function createModal(options: Omit<ModalType, 'open' | 'preRender'>): ModalInstance {\n let disposeRoot: (() => void) | null = null;\n let setIsOpen: ((v: boolean) => void) | null = null;\n let disposed = false;\n\n const doClose = (callOnClose: boolean) => {\n if (disposed) return;\n disposed = true;\n\n setIsOpen?.(false);\n if (callOnClose) options.onClose?.();\n\n const index = activeModalInstances.indexOf(instance);\n if (index > -1) {\n activeModalInstances.splice(index, 1);\n }\n\n setTimeout(() => {\n disposeRoot?.();\n }, 150);\n };\n\n createRoot(root => {\n disposeRoot = root;\n const [isOpen, _setIsOpen] = createSignal(true);\n setIsOpen = _setIsOpen;\n\n // ComponentModal renders via Portal (ZIndex → Portal) — it mounts itself\n // into document.body internally. We only need to call it inside a reactive\n // root so its signals/effects run; we don't need to insert it anywhere.\n createComponent(ComponentModal, {\n ...options,\n get open() {\n return isOpen();\n },\n preRender: false,\n onClose: () => doClose(true),\n });\n });\n\n const instance: ModalInstance = {\n destroy: () => doClose(false),\n };\n\n activeModalInstances.push(instance);\n return instance;\n}\n\nexport function closeAllModals() {\n const instances = [...activeModalInstances];\n instances.forEach(instance => instance.destroy());\n}\n"],"mappings":"yHAGA,IAAMK,EAAwC,EAAE,CAMhD,SAAgBG,EAAYC,EAA+D,CACzF,IAAIE,EAAmC,KACnCC,EAA2C,KAC3CE,EAAW,GAETC,EAAWC,GAAyB,CACxC,GAAIF,EAAU,OACdA,EAAW,GAEXF,IAAY,GAAM,CACdI,GAAaP,EAAQQ,WAAW,CAEpC,IAAMC,EAAQb,EAAqBc,QAAQC,EAAS,CAChDF,EAAQ,IACVb,EAAqBgB,OAAOH,EAAO,EAAE,CAGvCI,eAAiB,CACfX,KAAe,EACd,IAAI,EAGTV,EAAWsB,GAAQ,CACjBZ,EAAcY,EACd,GAAM,CAACC,EAAQC,GAAcvB,EAAa,GAAK,CAC/CU,EAAYa,EAKZzB,EAAgBG,EAAgB,CAC9B,GAAGM,EACH,IAAIiB,MAAO,CACT,OAAOF,GAAQ,EAEjBG,UAAW,GACXV,YAAeF,EAAQ,GAAI,CAC5B,CAAC,EACF,CAEF,IAAMK,EAA0B,CAC9Bb,YAAeQ,EAAQ,GAAK,CAC7B,CAGD,OADAV,EAAqBuB,KAAKR,EAAS,CAC5BA,EAGT,SAAgBS,GAAiB,CACb,CAAC,GAAGxB,EAAqB,CACjC0B,QAAQX,GAAYA,EAASb,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"modalContext.js","names":["createComponent","createRoot","createSignal","ComponentModal","ModalType","activeModalInstances","ModalInstance","destroy","createModal","options","Omit","disposeRoot","setIsOpen","v","disposed","doClose","callOnClose","onClose","index","indexOf","instance","splice","setTimeout","root","isOpen","_setIsOpen","open","preRender","push","closeAllModals","instances","forEach"],"sources":["../../../src/components/modal/modalContext.tsx"],"sourcesContent":["import { createComponent, createRoot, createSignal } from 'solid-js';\r\nimport { ComponentModal, ModalType } from './modal';\r\n\r\nconst activeModalInstances: ModalInstance[] = [];\r\n\r\ntype ModalInstance = {\r\n destroy: () => void;\r\n};\r\n\r\nexport function createModal(options: Omit<ModalType, 'open' | 'preRender'>): ModalInstance {\r\n let disposeRoot: (() => void) | null = null;\r\n let setIsOpen: ((v: boolean) => void) | null = null;\r\n let disposed = false;\r\n\r\n const doClose = (callOnClose: boolean) => {\r\n if (disposed) return;\r\n disposed = true;\r\n\r\n setIsOpen?.(false);\r\n if (callOnClose) options.onClose?.();\r\n\r\n const index = activeModalInstances.indexOf(instance);\r\n if (index > -1) {\r\n activeModalInstances.splice(index, 1);\r\n }\r\n\r\n setTimeout(() => {\r\n disposeRoot?.();\r\n }, 150);\r\n };\r\n\r\n createRoot(root => {\r\n disposeRoot = root;\r\n const [isOpen, _setIsOpen] = createSignal(true);\r\n setIsOpen = _setIsOpen;\r\n\r\n // ComponentModal renders via Portal (ZIndex → Portal) — it mounts itself\r\n // into document.body internally. We only need to call it inside a reactive\r\n // root so its signals/effects run; we don't need to insert it anywhere.\r\n createComponent(ComponentModal, {\r\n ...options,\r\n get open() {\r\n return isOpen();\r\n },\r\n preRender: false,\r\n onClose: () => doClose(true),\r\n });\r\n });\r\n\r\n const instance: ModalInstance = {\r\n destroy: () => doClose(false),\r\n };\r\n\r\n activeModalInstances.push(instance);\r\n return instance;\r\n}\r\n\r\nexport function closeAllModals() {\r\n const instances = [...activeModalInstances];\r\n instances.forEach(instance => instance.destroy());\r\n}\r\n"],"mappings":"yHAGA,IAAMK,EAAwC,EAAE,CAMhD,SAAgBG,EAAYC,EAA+D,CACzF,IAAIE,EAAmC,KACnCC,EAA2C,KAC3CE,EAAW,GAETC,EAAWC,GAAyB,CACxC,GAAIF,EAAU,OACdA,EAAW,GAEXF,IAAY,GAAM,CACdI,GAAaP,EAAQQ,WAAW,CAEpC,IAAMC,EAAQb,EAAqBc,QAAQC,EAAS,CAChDF,EAAQ,IACVb,EAAqBgB,OAAOH,EAAO,EAAE,CAGvCI,eAAiB,CACfX,KAAe,EACd,IAAI,EAGTV,EAAWsB,GAAQ,CACjBZ,EAAcY,EACd,GAAM,CAACC,EAAQC,GAAcvB,EAAa,GAAK,CAC/CU,EAAYa,EAKZzB,EAAgBG,EAAgB,CAC9B,GAAGM,EACH,IAAIiB,MAAO,CACT,OAAOF,GAAQ,EAEjBG,UAAW,GACXV,YAAeF,EAAQ,GAAI,CAC5B,CAAC,EACF,CAEF,IAAMK,EAA0B,CAC9Bb,YAAeQ,EAAQ,GAAK,CAC7B,CAGD,OADAV,EAAqBuB,KAAKR,EAAS,CAC5BA,EAGT,SAAgBS,GAAiB,CACb,CAAC,GAAGxB,EAAqB,CACjC0B,QAAQX,GAAYA,EAASb,SAAS,CAAC"}
|