@lumiastream/ui 0.1.0 → 0.2.1

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +327 -1
  2. package/dist/index.js +1919 -6
  3. package/package.json +59 -53
package/dist/index.js CHANGED
@@ -21,7 +21,7 @@ function styleInject(css, { insertAt } = {}) {
21
21
  }
22
22
 
23
23
  // src/tailwind.css
24
- styleInject('/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */\n@layer theme, base, components, utilities;\n@layer theme {\n :root,\n :host {\n --font-sans:\n ui-sans-serif,\n system-ui,\n sans-serif,\n "Apple Color Emoji",\n "Segoe UI Emoji",\n "Segoe UI Symbol",\n "Noto Color Emoji";\n --font-mono:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n "Liberation Mono",\n "Courier New",\n monospace;\n --color-blue-500: oklch(62.3% 0.214 259.815);\n --color-gray-500: oklch(55.1% 0.027 264.364);\n --spacing: 0.25rem;\n --text-sm: 0.875rem;\n --text-sm--line-height: calc(1.25 / 0.875);\n --text-base: 1rem;\n --text-base--line-height: calc(1.5 / 1);\n --text-lg: 1.125rem;\n --text-lg--line-height: calc(1.75 / 1.125);\n --default-font-family: var(--font-sans);\n --default-mono-font-family: var(--font-mono);\n }\n}\n@layer base {\n *,\n ::after,\n ::before,\n ::backdrop,\n ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html,\n :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");\n font-feature-settings: var(--default-font-feature-settings, normal);\n font-variation-settings: var(--default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b,\n strong {\n font-weight: bolder;\n }\n code,\n kbd,\n samp,\n pre {\n font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);\n font-feature-settings: var(--default-mono-font-feature-settings, normal);\n font-variation-settings: var(--default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub,\n sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol,\n ul,\n menu {\n list-style: none;\n }\n img,\n svg,\n video,\n canvas,\n audio,\n iframe,\n embed,\n object {\n display: block;\n vertical-align: middle;\n }\n img,\n video {\n max-width: 100%;\n height: auto;\n }\n button,\n input,\n select,\n optgroup,\n textarea,\n ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit,\n ::-webkit-datetime-edit-year-field,\n ::-webkit-datetime-edit-month-field,\n ::-webkit-datetime-edit-day-field,\n ::-webkit-datetime-edit-hour-field,\n ::-webkit-datetime-edit-minute-field,\n ::-webkit-datetime-edit-second-field,\n ::-webkit-datetime-edit-millisecond-field,\n ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n ::-webkit-calendar-picker-indicator {\n line-height: 1;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button,\n input:where([type=button], [type=reset], [type=submit]),\n ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button,\n ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden=until-found])) {\n display: none !important;\n }\n}\n@layer utilities {\n .static {\n position: static;\n }\n .start {\n inset-inline-start: var(--spacing);\n }\n .contents {\n display: contents;\n }\n .bg-blue-500 {\n background-color: var(--color-blue-500);\n }\n .bg-gray-500 {\n background-color: var(--color-gray-500);\n }\n .px-3 {\n padding-inline: calc(var(--spacing) * 3);\n }\n .px-4 {\n padding-inline: calc(var(--spacing) * 4);\n }\n .px-6 {\n padding-inline: calc(var(--spacing) * 6);\n }\n .py-1 {\n padding-block: calc(var(--spacing) * 1);\n }\n .py-2 {\n padding-block: calc(var(--spacing) * 2);\n }\n .py-3 {\n padding-block: calc(var(--spacing) * 3);\n }\n .text-base {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n .text-lg {\n font-size: var(--text-lg);\n line-height: var(--tw-leading, var(--text-lg--line-height));\n }\n .text-sm {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n}\n');
24
+ styleInject('/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root,\n :host {\n --font-sans:\n ui-sans-serif,\n system-ui,\n sans-serif,\n "Apple Color Emoji",\n "Segoe UI Emoji",\n "Segoe UI Symbol",\n "Noto Color Emoji";\n --font-mono:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n "Liberation Mono",\n "Courier New",\n monospace;\n --color-white: #fff;\n --spacing: 0.25rem;\n --text-sm: 0.875rem;\n --text-sm--line-height: calc(1.25 / 0.875);\n --text-base: 1rem;\n --text-base--line-height: calc(1.5 / 1);\n --text-lg: 1.125rem;\n --text-lg--line-height: calc(1.75 / 1.125);\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --radius-md: 0.375rem;\n --default-transition-duration: 150ms;\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --default-font-family: var(--font-sans);\n --default-mono-font-family: var(--font-mono);\n }\n}\n@layer base {\n *,\n ::after,\n ::before,\n ::backdrop,\n ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html,\n :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");\n font-feature-settings: var(--default-font-feature-settings, normal);\n font-variation-settings: var(--default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b,\n strong {\n font-weight: bolder;\n }\n code,\n kbd,\n samp,\n pre {\n font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);\n font-feature-settings: var(--default-mono-font-feature-settings, normal);\n font-variation-settings: var(--default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub,\n sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol,\n ul,\n menu {\n list-style: none;\n }\n img,\n svg,\n video,\n canvas,\n audio,\n iframe,\n embed,\n object {\n display: block;\n vertical-align: middle;\n }\n img,\n video {\n max-width: 100%;\n height: auto;\n }\n button,\n input,\n select,\n optgroup,\n textarea,\n ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit,\n ::-webkit-datetime-edit-year-field,\n ::-webkit-datetime-edit-month-field,\n ::-webkit-datetime-edit-day-field,\n ::-webkit-datetime-edit-hour-field,\n ::-webkit-datetime-edit-minute-field,\n ::-webkit-datetime-edit-second-field,\n ::-webkit-datetime-edit-millisecond-field,\n ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n ::-webkit-calendar-picker-indicator {\n line-height: 1;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button,\n input:where([type=button], [type=reset], [type=submit]),\n ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button,\n ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden=until-found])) {\n display: none !important;\n }\n}\n@layer utilities {\n .visible {\n visibility: visible;\n }\n .absolute {\n position: absolute;\n }\n .relative {\n position: relative;\n }\n .static {\n position: static;\n }\n .start {\n inset-inline-start: var(--spacing);\n }\n .end {\n inset-inline-end: var(--spacing);\n }\n .mr-2\\.5 {\n margin-right: calc(var(--spacing) * 2.5);\n }\n .mb-1 {\n margin-bottom: calc(var(--spacing) * 1);\n }\n .mb-2\\.5 {\n margin-bottom: calc(var(--spacing) * 2.5);\n }\n .ml-2 {\n margin-left: calc(var(--spacing) * 2);\n }\n .block {\n display: block;\n }\n .contents {\n display: contents;\n }\n .flex {\n display: flex;\n }\n .grid {\n display: grid;\n }\n .inline-flex {\n display: inline-flex;\n }\n .h-6 {\n height: calc(var(--spacing) * 6);\n }\n .h-\\[18px\\] {\n height: 18px;\n }\n .h-full {\n height: 100%;\n }\n .max-h-\\[55vh\\] {\n max-height: 55vh;\n }\n .min-h-\\[50vh\\] {\n min-height: 50vh;\n }\n .min-h-screen {\n min-height: 100vh;\n }\n .w-6 {\n width: calc(var(--spacing) * 6);\n }\n .w-\\[18px\\] {\n width: 18px;\n }\n .w-\\[92vw\\] {\n width: 92vw;\n }\n .w-full {\n width: 100%;\n }\n .max-w-\\[600px\\] {\n max-width: 600px;\n }\n .max-w-\\[1100px\\] {\n max-width: 1100px;\n }\n .min-w-0 {\n min-width: calc(var(--spacing) * 0);\n }\n .flex-1 {\n flex: 1;\n }\n .shrink {\n flex-shrink: 1;\n }\n .shrink-0 {\n flex-shrink: 0;\n }\n .transform {\n transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);\n }\n .cursor-pointer {\n cursor: pointer;\n }\n .grid-cols-\\[minmax\\(300px\\,1\\.5fr\\)_2fr\\] {\n grid-template-columns: minmax(300px, 1.5fr) 2fr;\n }\n .flex-col {\n flex-direction: column;\n }\n .flex-nowrap {\n flex-wrap: nowrap;\n }\n .items-center {\n align-items: center;\n }\n .justify-between {\n justify-content: space-between;\n }\n .justify-center {\n justify-content: center;\n }\n .gap-2 {\n gap: calc(var(--spacing) * 2);\n }\n .gap-4 {\n gap: calc(var(--spacing) * 4);\n }\n .overflow-auto {\n overflow: auto;\n }\n .overflow-hidden {\n overflow: hidden;\n }\n .rounded {\n border-radius: 0.25rem;\n }\n .rounded-md {\n border-radius: var(--radius-md);\n }\n .border {\n border-style: var(--tw-border-style);\n border-width: 1px;\n }\n .border-b {\n border-bottom-style: var(--tw-border-style);\n border-bottom-width: 1px;\n }\n .border-\\[var\\(--neutralLight3\\,\\#9392a1\\)\\] {\n border-color: var(--neutralLight3,#9392a1);\n }\n .border-current {\n border-color: currentcolor;\n }\n .border-white\\/10 {\n border-color: color-mix(in srgb, #fff 10%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n border-color: color-mix(in oklab, var(--color-white) 10%, transparent);\n }\n }\n .border-white\\/25 {\n border-color: color-mix(in srgb, #fff 25%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n border-color: color-mix(in oklab, var(--color-white) 25%, transparent);\n }\n }\n .bg-\\[\\#1b1a28\\] {\n background-color: #1b1a28;\n }\n .bg-cover {\n background-size: cover;\n }\n .bg-center {\n background-position: center;\n }\n .bg-no-repeat {\n background-repeat: no-repeat;\n }\n .p-0 {\n padding: calc(var(--spacing) * 0);\n }\n .p-6 {\n padding: calc(var(--spacing) * 6);\n }\n .px-1 {\n padding-inline: calc(var(--spacing) * 1);\n }\n .px-3 {\n padding-inline: calc(var(--spacing) * 3);\n }\n .px-4 {\n padding-inline: calc(var(--spacing) * 4);\n }\n .px-6 {\n padding-inline: calc(var(--spacing) * 6);\n }\n .py-0 {\n padding-block: calc(var(--spacing) * 0);\n }\n .py-1 {\n padding-block: calc(var(--spacing) * 1);\n }\n .py-2 {\n padding-block: calc(var(--spacing) * 2);\n }\n .py-3 {\n padding-block: calc(var(--spacing) * 3);\n }\n .py-\\[18px\\] {\n padding-block: 18px;\n }\n .pr-4 {\n padding-right: calc(var(--spacing) * 4);\n }\n .text-base {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n .text-lg {\n font-size: var(--text-lg);\n line-height: var(--tw-leading, var(--text-lg--line-height));\n }\n .text-sm {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n .text-\\[10px\\] {\n font-size: 10px;\n }\n .leading-none {\n --tw-leading: 1;\n line-height: 1;\n }\n .font-medium {\n --tw-font-weight: var(--font-weight-medium);\n font-weight: var(--font-weight-medium);\n }\n .font-semibold {\n --tw-font-weight: var(--font-weight-semibold);\n font-weight: var(--font-weight-semibold);\n }\n .break-words {\n overflow-wrap: break-word;\n }\n .break-all {\n word-break: break-all;\n }\n .text-ellipsis {\n text-overflow: ellipsis;\n }\n .whitespace-nowrap {\n white-space: nowrap;\n }\n .text-\\[\\#f4f3ff\\] {\n color: #f4f3ff;\n }\n .text-\\[var\\(--customVariables\\,\\#69ffd2\\)\\] {\n color: var(--customVariables,#69ffd2);\n }\n .text-\\[var\\(--functionVariables\\,var\\(--semanticPurple\\,\\#b489ff\\)\\)\\] {\n color: var(--functionVariables,var(--semanticPurple,#b489ff));\n }\n .text-\\[var\\(--neutralLight1\\,\\#f4f3ff\\)\\] {\n color: var(--neutralLight1,#f4f3ff);\n }\n .text-\\[var\\(--neutralLight2\\,\\#cac9d5\\)\\] {\n color: var(--neutralLight2,#cac9d5);\n }\n .text-\\[var\\(--neutralLight3\\,\\#9392a1\\)\\] {\n color: var(--neutralLight3,#9392a1);\n }\n .text-\\[var\\(--normalVariables\\,var\\(--semanticBlue\\,\\#65b8ff\\)\\)\\] {\n color: var(--normalVariables,var(--semanticBlue,#65b8ff));\n }\n .uppercase {\n text-transform: uppercase;\n }\n .shadow-\\[0_0_0_1px_rgba\\(0\\,0\\,0\\,0\\.25\\)\\] {\n --tw-shadow: 0 0 0 1px var(--tw-shadow-color, rgba(0,0,0,0.25));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n }\n .shadow-\\[0_8px_18px_rgba\\(0\\,0\\,0\\,0\\.18\\)\\] {\n --tw-shadow: 0 8px 18px var(--tw-shadow-color, rgba(0,0,0,0.18));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n }\n .filter {\n filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);\n }\n .transition {\n transition-property:\n color,\n background-color,\n border-color,\n outline-color,\n text-decoration-color,\n fill,\n stroke,\n --tw-gradient-from,\n --tw-gradient-via,\n --tw-gradient-to,\n opacity,\n box-shadow,\n transform,\n translate,\n scale,\n rotate,\n filter,\n -webkit-backdrop-filter,\n backdrop-filter,\n display,\n content-visibility,\n overlay,\n pointer-events;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .\\[--neutralDark1\\:\\#1b1a28\\] {\n --neutralDark1: #1b1a28;\n }\n .\\[--neutralDark2\\:\\#252338\\] {\n --neutralDark2: #252338;\n }\n .\\[--neutralDark3\\:\\#312f47\\] {\n --neutralDark3: #312f47;\n }\n .\\[--neutralDark4\\:\\#46435f\\] {\n --neutralDark4: #46435f;\n }\n .\\[--neutralLight1\\:\\#f4f3ff\\] {\n --neutralLight1: #f4f3ff;\n }\n .\\[--neutralLight2\\:\\#cac9d5\\] {\n --neutralLight2: #cac9d5;\n }\n .\\[--neutralLight3\\:\\#9f9eb2\\] {\n --neutralLight3: #9f9eb2;\n }\n .\\[--primary\\:\\#ff4076\\] {\n --primary: #ff4076;\n }\n .\\[--radiusContainer\\:12px\\] {\n --radiusContainer: 12px;\n }\n .\\[--radiusContainerSm\\:10px\\] {\n --radiusContainerSm: 10px;\n }\n .\\[--secondary\\:\\#5f5dff\\] {\n --secondary: #5f5dff;\n }\n .\\[--variable-custom-color\\:var\\(--customVariables\\,\\#69ffd2\\)\\] {\n --variable-custom-color: var(--customVariables,#69ffd2);\n }\n .\\[--variable-function-color\\:var\\(--functionVariables\\,var\\(--semanticPurple\\,\\#b489ff\\)\\)\\] {\n --variable-function-color: var(--functionVariables,var(--semanticPurple,#b489ff));\n }\n .\\[--variable-normal-color\\:var\\(--normalVariables\\,var\\(--semanticBlue\\,\\#65b8ff\\)\\)\\] {\n --variable-normal-color: var(--normalVariables,var(--semanticBlue,#65b8ff));\n }\n .hover\\:brightness-110 {\n &:hover {\n @media (hover: hover) {\n --tw-brightness: brightness(110%);\n filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);\n }\n }\n }\n .focus\\:ring-2 {\n &:focus {\n --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n }\n }\n .focus\\:ring-\\[var\\(--primary\\,\\#ff4076\\)\\] {\n &:focus {\n --tw-ring-color: var(--primary,#ff4076);\n }\n }\n .focus\\:ring-offset-2 {\n &:focus {\n --tw-ring-offset-width: 2px;\n --tw-ring-offset-shadow: var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n }\n }\n .focus\\:ring-offset-\\[var\\(--neutralDark1\\,\\#1b1a28\\)\\] {\n &:focus {\n --tw-ring-offset-color: var(--neutralDark1,#1b1a28);\n }\n }\n .focus\\:outline-none {\n &:focus {\n --tw-outline-style: none;\n outline-style: none;\n }\n }\n .active\\:opacity-80 {\n &:active {\n opacity: 80%;\n }\n }\n .active\\:brightness-95 {\n &:active {\n --tw-brightness: brightness(95%);\n filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);\n }\n }\n .disabled\\:cursor-not-allowed {\n &:disabled {\n cursor: not-allowed;\n }\n }\n .disabled\\:opacity-50 {\n &:disabled {\n opacity: 50%;\n }\n }\n .\\[\\&_circle\\]\\:stroke-white {\n & circle {\n stroke: var(--color-white);\n }\n }\n .\\[\\&_polyline\\]\\:stroke-white {\n & polyline {\n stroke: var(--color-white);\n }\n }\n}\n@property --tw-rotate-x { syntax: "*"; inherits: false; }\n@property --tw-rotate-y { syntax: "*"; inherits: false; }\n@property --tw-rotate-z { syntax: "*"; inherits: false; }\n@property --tw-skew-x { syntax: "*"; inherits: false; }\n@property --tw-skew-y { syntax: "*"; inherits: false; }\n@property --tw-border-style { syntax: "*"; inherits: false; initial-value: solid; }\n@property --tw-leading { syntax: "*"; inherits: false; }\n@property --tw-font-weight { syntax: "*"; inherits: false; }\n@property --tw-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-inset-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-inset-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-inset-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-ring-color { syntax: "*"; inherits: false; }\n@property --tw-ring-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-inset-ring-color { syntax: "*"; inherits: false; }\n@property --tw-inset-ring-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-ring-inset { syntax: "*"; inherits: false; }\n@property --tw-ring-offset-width { syntax: "<length>"; inherits: false; initial-value: 0px; }\n@property --tw-ring-offset-color { syntax: "*"; inherits: false; initial-value: #fff; }\n@property --tw-ring-offset-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-blur { syntax: "*"; inherits: false; }\n@property --tw-brightness { syntax: "*"; inherits: false; }\n@property --tw-contrast { syntax: "*"; inherits: false; }\n@property --tw-grayscale { syntax: "*"; inherits: false; }\n@property --tw-hue-rotate { syntax: "*"; inherits: false; }\n@property --tw-invert { syntax: "*"; inherits: false; }\n@property --tw-opacity { syntax: "*"; inherits: false; }\n@property --tw-saturate { syntax: "*"; inherits: false; }\n@property --tw-sepia { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-drop-shadow-size { syntax: "*"; inherits: false; }\n@layer properties {\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n *,\n ::before,\n ::after,\n ::backdrop {\n --tw-rotate-x: initial;\n --tw-rotate-y: initial;\n --tw-rotate-z: initial;\n --tw-skew-x: initial;\n --tw-skew-y: initial;\n --tw-border-style: solid;\n --tw-leading: initial;\n --tw-font-weight: initial;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-color: initial;\n --tw-shadow-alpha: 100%;\n --tw-inset-shadow: 0 0 #0000;\n --tw-inset-shadow-color: initial;\n --tw-inset-shadow-alpha: 100%;\n --tw-ring-color: initial;\n --tw-ring-shadow: 0 0 #0000;\n --tw-inset-ring-color: initial;\n --tw-inset-ring-shadow: 0 0 #0000;\n --tw-ring-inset: initial;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-blur: initial;\n --tw-brightness: initial;\n --tw-contrast: initial;\n --tw-grayscale: initial;\n --tw-hue-rotate: initial;\n --tw-invert: initial;\n --tw-opacity: initial;\n --tw-saturate: initial;\n --tw-sepia: initial;\n --tw-drop-shadow: initial;\n --tw-drop-shadow-color: initial;\n --tw-drop-shadow-alpha: 100%;\n --tw-drop-shadow-size: initial;\n }\n }\n}\n');
25
25
 
26
26
  // src/components/LSButton/LSButton.tsx
27
27
  import { jsx } from "react/jsx-runtime";
@@ -32,23 +32,1313 @@ var LSButton = ({
32
32
  label,
33
33
  ...props
34
34
  }) => {
35
- const mode = primary ? "bg-blue-500" : "bg-gray-500";
35
+ const background = backgroundColor ?? (primary ? "var(--primary, #ff4076)" : "var(--neutralDark4, #46435f)");
36
36
  return /* @__PURE__ */ jsx(
37
37
  "button",
38
38
  {
39
39
  type: "button",
40
40
  className: [
41
- "bg-blue-500",
42
- size === "small" ? "px-3 py-1 text-sm" : size === "large" ? "px-6 py-3 text-lg" : "px-4 py-2 text-base",
43
- mode,
44
- backgroundColor ? `bg-[${backgroundColor}]` : ""
41
+ "rounded-md border border-white/10 font-medium text-[var(--neutralLight1,#f4f3ff)] shadow-[0_8px_18px_rgba(0,0,0,0.18)] transition hover:brightness-110 focus:outline-none focus:ring-2 focus:ring-[var(--primary,#ff4076)] focus:ring-offset-2 focus:ring-offset-[var(--neutralDark1,#1b1a28)] active:brightness-95",
42
+ size === "small" ? "px-3 py-1 text-sm" : size === "large" ? "px-6 py-3 text-lg" : "px-4 py-2 text-base"
45
43
  ].join(" "),
44
+ style: { background },
46
45
  ...props,
47
46
  children: label
48
47
  }
49
48
  );
50
49
  };
51
50
 
51
+ // src/components/LSInput/LSInput.tsx
52
+ import FormControl from "@mui/material/FormControl";
53
+ import InputAdornment from "@mui/material/InputAdornment";
54
+ import TextField from "@mui/material/TextField";
55
+ import classNames from "classnames";
56
+ import { forwardRef } from "react";
57
+ import { jsx as jsx2 } from "react/jsx-runtime";
58
+ var LSInput = forwardRef(
59
+ (props, ref) => {
60
+ const hasExplicitValue = Object.prototype.hasOwnProperty.call(props, "value");
61
+ const {
62
+ startAdornment,
63
+ endAdornment,
64
+ inputBeforeText,
65
+ inputAfterText,
66
+ maxWidth,
67
+ className = "",
68
+ InputProps: inputPropsProp,
69
+ InputLabelProps: inputLabelPropsProp,
70
+ inputProps: htmlInputPropsProp,
71
+ slotProps: slotPropsProp,
72
+ onChange,
73
+ onChangeStart,
74
+ onChangeEnd,
75
+ type,
76
+ value,
77
+ helperText,
78
+ error,
79
+ style,
80
+ centerText,
81
+ $noMinHeight,
82
+ bypasscolor,
83
+ textColor,
84
+ fullWidth = true,
85
+ ...rest
86
+ } = props;
87
+ const isNumberInput = type === "number";
88
+ const labelIdFallback = typeof rest.label === "string" ? rest.label : void 0;
89
+ const normalizedValue = isNumberInput && (value === void 0 || value === null) ? "" : value;
90
+ const handleChange = (event) => {
91
+ const rawValue = event.target.value;
92
+ let sanitizedValue = rawValue;
93
+ if (isNumberInput) {
94
+ if (rawValue === "") {
95
+ sanitizedValue = void 0;
96
+ } else {
97
+ const numericValue = Number(rawValue);
98
+ sanitizedValue = Number.isNaN(numericValue) ? void 0 : numericValue;
99
+ }
100
+ }
101
+ onChangeStart?.(event, sanitizedValue);
102
+ onChange?.(event, sanitizedValue);
103
+ onChangeEnd?.(event, sanitizedValue);
104
+ };
105
+ const resolvedStartAdornment = inputPropsProp?.startAdornment ?? (startAdornment ? /* @__PURE__ */ jsx2(InputAdornment, { position: "start", children: startAdornment }) : inputBeforeText ? /* @__PURE__ */ jsx2(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx2("span", { className: "mui-ls-input-affix", children: inputBeforeText }) }) : void 0);
106
+ const resolvedEndAdornment = inputPropsProp?.endAdornment ?? (endAdornment ? /* @__PURE__ */ jsx2(InputAdornment, { position: "end", children: endAdornment }) : inputAfterText ? /* @__PURE__ */ jsx2(InputAdornment, { position: "end", children: /* @__PURE__ */ jsx2("span", { className: "mui-ls-input-affix", children: inputAfterText }) }) : void 0);
107
+ const inputSlotProps = {
108
+ ...inputPropsProp,
109
+ startAdornment: resolvedStartAdornment,
110
+ endAdornment: resolvedEndAdornment,
111
+ readOnly: rest.readOnly ?? inputPropsProp?.readOnly,
112
+ sx: {
113
+ ...inputPropsProp?.sx ?? {},
114
+ "& input, & textarea": {
115
+ textAlign: centerText ? "center" : void 0,
116
+ color: textColor ?? void 0
117
+ }
118
+ }
119
+ };
120
+ const inputLabelProps = {
121
+ shrink: true,
122
+ ...inputLabelPropsProp
123
+ };
124
+ const helperContent = helperText ?? (typeof error === "string" ? error : "");
125
+ const hasError = typeof error === "string" ? true : Boolean(error);
126
+ const resolvedMaxWidth = maxWidth ?? style?.maxWidth;
127
+ const valueProps = hasExplicitValue ? { value: normalizedValue } : {};
128
+ const slotProps = {
129
+ ...slotPropsProp ?? {},
130
+ input: {
131
+ ...slotPropsProp?.input ?? {},
132
+ ...inputSlotProps,
133
+ sx: {
134
+ ...slotPropsProp?.input?.sx ?? {},
135
+ ...inputSlotProps.sx
136
+ }
137
+ },
138
+ inputLabel: {
139
+ ...slotPropsProp?.inputLabel ?? {},
140
+ ...inputLabelProps
141
+ },
142
+ htmlInput: {
143
+ ...slotPropsProp?.htmlInput ?? {},
144
+ ...htmlInputPropsProp ?? {}
145
+ }
146
+ };
147
+ const TextFieldComponent = TextField;
148
+ return /* @__PURE__ */ jsx2(
149
+ FormControl,
150
+ {
151
+ variant: "outlined",
152
+ className: classNames("mui-ls-input w-full", className, {
153
+ noMinHeight: $noMinHeight,
154
+ bypassMuiColor: bypasscolor || bypasscolor === "default"
155
+ }),
156
+ style: { ...style, maxWidth: resolvedMaxWidth, width: fullWidth ? "100%" : style?.width },
157
+ children: /* @__PURE__ */ jsx2(
158
+ TextFieldComponent,
159
+ {
160
+ ...rest,
161
+ ...valueProps,
162
+ type,
163
+ id: rest.id ?? rest.name ?? labelIdFallback,
164
+ label: rest.label,
165
+ size: rest.size,
166
+ margin: "dense",
167
+ variant: "outlined",
168
+ color: bypasscolor === "default" || bypasscolor === "inherit" ? "primary" : bypasscolor,
169
+ fullWidth,
170
+ onChange: handleChange,
171
+ slotProps,
172
+ inputRef: ref,
173
+ helperText: helperContent,
174
+ error: hasError
175
+ }
176
+ )
177
+ }
178
+ );
179
+ }
180
+ );
181
+ LSInput.displayName = "LSInput";
182
+
183
+ // src/components/LSSliderInput/LSSliderInput.tsx
184
+ import Slider from "@mui/material/Slider";
185
+ import classNames2 from "classnames";
186
+ import { useCallback, useEffect, useMemo, useState } from "react";
187
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
188
+ var LSSliderInput = ({
189
+ name,
190
+ value,
191
+ defaultValue,
192
+ isFloat,
193
+ isMiliseconds,
194
+ isFloatMiliseconds,
195
+ label,
196
+ inline,
197
+ hasInfo,
198
+ infoOpen,
199
+ infoClose,
200
+ max = Number.MAX_SAFE_INTEGER,
201
+ min = 0,
202
+ step = 1,
203
+ type = "number",
204
+ inputAfterText,
205
+ onChange,
206
+ inputProps = {},
207
+ helperText,
208
+ fullWidth = false,
209
+ hideInput = false,
210
+ hideSlider = false,
211
+ valueLabelFormat,
212
+ ...rest
213
+ }) => {
214
+ const isValueFloat = Boolean(isFloat || isFloatMiliseconds || isMiliseconds);
215
+ const actualToDisplay = useCallback(
216
+ (input) => {
217
+ if (input === void 0 || input === null) {
218
+ return input;
219
+ }
220
+ const numericValue = Number(input);
221
+ if (Number.isNaN(numericValue)) {
222
+ return 0;
223
+ }
224
+ if (!isValueFloat) {
225
+ return numericValue;
226
+ }
227
+ const divisor = isFloatMiliseconds ? 1e3 : 1;
228
+ return Number((numericValue / divisor).toFixed(1));
229
+ },
230
+ [isFloatMiliseconds, isValueFloat]
231
+ );
232
+ const displayStep = useMemo(() => actualToDisplay(step), [actualToDisplay, step]);
233
+ const resolvedDefaultValue = defaultValue ?? 0;
234
+ const [displayValue, setDisplayValue] = useState(() => actualToDisplay(defaultValue ?? value ?? resolvedDefaultValue));
235
+ const displayMaximum = useMemo(() => actualToDisplay(max), [actualToDisplay, max]);
236
+ const displayMinimum = useMemo(() => actualToDisplay(min), [actualToDisplay, min]);
237
+ const sliderValue = typeof displayValue === "number" ? Math.min(displayMaximum, Math.max(displayMinimum, displayValue)) : displayMinimum;
238
+ const stepPrecision = useMemo(() => {
239
+ const stepString = String(displayStep);
240
+ const decimalIndex = stepString.indexOf(".");
241
+ return decimalIndex === -1 ? 0 : stepString.length - decimalIndex - 1;
242
+ }, [displayStep]);
243
+ useEffect(() => {
244
+ if (typeof value === "number" && Number.isNaN(value) === false) {
245
+ setDisplayValue(actualToDisplay(value));
246
+ }
247
+ }, [actualToDisplay, value]);
248
+ const normalizeDisplayValue = useCallback(
249
+ (input) => {
250
+ const bounded = Math.min(displayMaximum, Math.max(displayMinimum, input));
251
+ if (!Number.isFinite(displayStep) || displayStep <= 0) {
252
+ return bounded;
253
+ }
254
+ const snapped = Math.round((bounded - displayMinimum) / displayStep) * displayStep + displayMinimum;
255
+ return Number(snapped.toFixed(stepPrecision));
256
+ },
257
+ [displayMaximum, displayMinimum, displayStep, stepPrecision]
258
+ );
259
+ const handleInputChange = useCallback(
260
+ ({ target: { value: inputValue } }) => {
261
+ setDisplayValue(inputValue ?? "");
262
+ if (inputValue === "" || inputValue === null) {
263
+ if (typeof onChange === "function") {
264
+ onChange(void 0);
265
+ }
266
+ return;
267
+ }
268
+ const numericValue = Number(inputValue);
269
+ if (Number.isNaN(numericValue)) {
270
+ return;
271
+ }
272
+ const normalizedDisplayValue = normalizeDisplayValue(numericValue);
273
+ const updatedValue = isFloatMiliseconds ? normalizedDisplayValue * 1e3 : normalizedDisplayValue;
274
+ const upperBound = typeof max === "number" ? max : Number.MAX_SAFE_INTEGER;
275
+ const lowerBound = typeof min === "number" ? min : 0;
276
+ const isValid = updatedValue >= lowerBound && updatedValue <= upperBound;
277
+ if (isValid && typeof onChange === "function") {
278
+ onChange(updatedValue);
279
+ }
280
+ },
281
+ [isFloatMiliseconds, max, min, normalizeDisplayValue, onChange]
282
+ );
283
+ const handleSliderChange = useCallback(
284
+ (_, sliderInputValue) => {
285
+ const numericValue = typeof sliderInputValue === "number" ? sliderInputValue : sliderInputValue[0];
286
+ const normalizedDisplayValue = normalizeDisplayValue(numericValue);
287
+ setDisplayValue(normalizedDisplayValue);
288
+ const nextValue = isFloatMiliseconds ? normalizedDisplayValue * 1e3 : normalizedDisplayValue;
289
+ onChange?.(nextValue);
290
+ },
291
+ [isFloatMiliseconds, normalizeDisplayValue, onChange]
292
+ );
293
+ const controlsRow = /* @__PURE__ */ jsxs(
294
+ "div",
295
+ {
296
+ className: classNames2("mui-ls-slider-input-row", {
297
+ "mui-ls-slider-input-row--slider": !hideSlider,
298
+ "mui-ls-slider-input-row--input": hideInput
299
+ }),
300
+ children: [
301
+ !hideSlider && /* @__PURE__ */ jsx3(
302
+ Slider,
303
+ {
304
+ value: sliderValue,
305
+ onChange: handleSliderChange,
306
+ onBlur: rest.onBlur,
307
+ color: "primary",
308
+ valueLabelDisplay: "auto",
309
+ valueLabelFormat: (v) => valueLabelFormat?.(v) ?? `${v}${inputAfterText ?? ""}`,
310
+ min: displayMinimum,
311
+ max: displayMaximum,
312
+ step: displayStep,
313
+ sx: { flex: 1, minWidth: 0 }
314
+ }
315
+ ),
316
+ !hideInput && /* @__PURE__ */ jsx3(
317
+ LSInput,
318
+ {
319
+ ...rest,
320
+ ...inputProps,
321
+ type,
322
+ name,
323
+ onChange: (_event, nextValue) => handleInputChange({ target: { value: nextValue ?? "" } }),
324
+ value: displayValue ?? "",
325
+ inputAfterText,
326
+ InputProps: {
327
+ ...inputProps?.InputProps ?? {},
328
+ name,
329
+ type: "number",
330
+ value: displayValue,
331
+ min: displayMinimum,
332
+ max: displayMaximum,
333
+ step: displayStep,
334
+ inputMode: stepPrecision > 0 ? "decimal" : "numeric"
335
+ },
336
+ fullWidth: hideSlider ? fullWidth : false,
337
+ $noMinHeight: !fullWidth,
338
+ className: hideSlider ? inputProps?.className : `${inputProps?.className ?? ""} small noMinHeight`.trim(),
339
+ style: hideSlider ? inputProps?.style : { width: 96, maxWidth: 96, flexShrink: 0 },
340
+ ...!hideSlider ? { size: "small" } : {}
341
+ }
342
+ )
343
+ ]
344
+ }
345
+ );
346
+ return /* @__PURE__ */ jsxs("div", { className: classNames2("mui-ls-slider-input-root", { "mui-ls-slider-input-root--fullWidth": fullWidth }), children: [
347
+ /* @__PURE__ */ jsxs(
348
+ "fieldset",
349
+ {
350
+ className: classNames2("mui-ls-slider-input-fieldset", {
351
+ "mui-ls-slider-input-fieldset--fullWidth": fullWidth
352
+ }),
353
+ children: [
354
+ label && /* @__PURE__ */ jsx3("legend", { className: "mui-ls-slider-input-legend", children: label }),
355
+ controlsRow
356
+ ]
357
+ }
358
+ ),
359
+ helperText && /* @__PURE__ */ jsx3("small", { className: "mui-ls-slider-input-helper", children: helperText })
360
+ ] });
361
+ };
362
+ LSSliderInput.displayName = "LSSliderInput";
363
+
364
+ // src/components/LSSelect/LSSelect.tsx
365
+ import FormControl2 from "@mui/material/FormControl";
366
+ import InputLabel from "@mui/material/InputLabel";
367
+ import Select from "@mui/material/Select";
368
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
369
+ var LSSelect = ({ className = "", style, ...props }) => {
370
+ const { placeholder, displayEmpty: displayEmptyProp, renderValue: renderValueProp, variant: _variant, MenuProps, ...rest } = props;
371
+ const labelKey = props.name ?? (typeof props.label === "string" ? props.label : void 0);
372
+ const labelId = props.label && labelKey ? `label_${labelKey}` : void 0;
373
+ const placeholderText = typeof placeholder === "string" ? placeholder : "";
374
+ const displayEmpty = displayEmptyProp ?? !!placeholderText;
375
+ const value = rest.multiple === true ? Array.isArray(rest.value) ? rest.value : rest.value === void 0 || rest.value === null || rest.value === "" ? [] : [rest.value] : rest.value ?? "";
376
+ const renderValue = renderValueProp ?? (placeholderText ? (selected) => {
377
+ if (selected === "" || Array.isArray(selected) && selected.length === 0) {
378
+ return /* @__PURE__ */ jsx4("span", { style: { color: "var(--neutralLight3)" }, children: placeholderText });
379
+ }
380
+ return Array.isArray(selected) ? selected.join(", ") : selected;
381
+ } : void 0);
382
+ const mergedMenuProps = {
383
+ ...MenuProps ?? {},
384
+ slotProps: {
385
+ ...MenuProps?.slotProps ?? {},
386
+ paper: {
387
+ ...MenuProps?.slotProps?.paper ?? {},
388
+ sx: {
389
+ background: "var(--neutralDark2) !important",
390
+ backgroundColor: "var(--neutralDark2)",
391
+ color: "var(--neutralLight1)",
392
+ border: "1px solid var(--neutralDark4)",
393
+ boxShadow: "0 16px 32px rgba(0, 0, 0, 0.32)",
394
+ ...MenuProps?.slotProps?.paper?.sx
395
+ }
396
+ },
397
+ list: {
398
+ ...MenuProps?.slotProps?.list ?? {},
399
+ sx: {
400
+ backgroundColor: "var(--neutralDark2)",
401
+ color: "var(--neutralLight1)",
402
+ ...MenuProps?.slotProps?.list?.sx
403
+ }
404
+ }
405
+ },
406
+ PaperProps: {
407
+ ...MenuProps?.PaperProps ?? {},
408
+ sx: {
409
+ background: "var(--neutralDark2) !important",
410
+ backgroundColor: "var(--neutralDark2)",
411
+ color: "var(--neutralLight1)",
412
+ border: "1px solid var(--neutralDark4)",
413
+ boxShadow: "0 16px 32px rgba(0, 0, 0, 0.32)",
414
+ "& .MuiList-root": {
415
+ backgroundColor: "var(--neutralDark2)"
416
+ },
417
+ "& .MuiListSubheader-root": {
418
+ backgroundColor: "var(--neutralDark1)",
419
+ color: "var(--neutralLight2)"
420
+ },
421
+ "& .MuiMenuItem-root": {
422
+ color: "var(--neutralLight1)"
423
+ },
424
+ ...MenuProps?.PaperProps?.sx
425
+ }
426
+ }
427
+ };
428
+ return /* @__PURE__ */ jsxs2(FormControl2, { variant: "outlined", className: `${className} mui-ls-select-form-control`, sx: { marginBottom: ".3rem", marginTop: ".5rem", minWidth: "100px", width: "100%" }, size: rest.size, style, children: [
429
+ props.label && /* @__PURE__ */ jsx4(InputLabel, { shrink: true, id: labelId, children: props.label }),
430
+ /* @__PURE__ */ jsx4(
431
+ Select,
432
+ {
433
+ MenuProps: mergedMenuProps,
434
+ className: "mui-ls-select",
435
+ variant: "outlined",
436
+ labelId,
437
+ label: props.label,
438
+ displayEmpty,
439
+ renderValue,
440
+ ...rest,
441
+ value,
442
+ children: props.children
443
+ }
444
+ )
445
+ ] });
446
+ };
447
+ LSSelect.displayName = "LSSelect";
448
+
449
+ // src/components/LSCheckbox/LSCheckbox.tsx
450
+ import Checkbox from "@mui/material/Checkbox";
451
+ import FormControlLabel from "@mui/material/FormControlLabel";
452
+ import { forwardRef as forwardRef2 } from "react";
453
+ import { useController, useFormContext } from "react-hook-form";
454
+ import classNames3 from "classnames";
455
+ import { jsx as jsx5 } from "react/jsx-runtime";
456
+ var LSCheckbox = forwardRef2(({ className = "", checked, inputRef, slotProps, ...props }, ref) => {
457
+ const CheckboxComponent = Checkbox;
458
+ return /* @__PURE__ */ jsx5(
459
+ CheckboxComponent,
460
+ {
461
+ ...props,
462
+ checked,
463
+ className: classNames3("ls-checkbox", className, { "Mui-disabled": props.disabled }),
464
+ ref,
465
+ slotProps: {
466
+ ...slotProps ?? {},
467
+ input: {
468
+ ...slotProps?.input ?? {},
469
+ ref: inputRef ?? slotProps?.input?.ref
470
+ }
471
+ }
472
+ }
473
+ );
474
+ });
475
+ LSCheckbox.displayName = "LSCheckbox";
476
+ function LSCheckboxField({
477
+ name,
478
+ label,
479
+ control,
480
+ className = "",
481
+ disabled,
482
+ labelPlacement = "end",
483
+ checkboxProps
484
+ }) {
485
+ const formContext = useFormContext();
486
+ const resolvedControl = control ?? formContext.control;
487
+ const { field } = useController({ name, control: resolvedControl });
488
+ return /* @__PURE__ */ jsx5(
489
+ FormControlLabel,
490
+ {
491
+ className: classNames3("ls-checkbox-row", className),
492
+ labelPlacement,
493
+ disabled,
494
+ control: /* @__PURE__ */ jsx5(
495
+ LSCheckbox,
496
+ {
497
+ ...checkboxProps,
498
+ name: field.name,
499
+ checked: Boolean(field.value),
500
+ onBlur: field.onBlur,
501
+ onChange: (_event, checked) => field.onChange(checked),
502
+ inputRef: field.ref,
503
+ disabled: disabled ?? checkboxProps?.disabled
504
+ }
505
+ ),
506
+ label
507
+ }
508
+ );
509
+ }
510
+
511
+ // src/components/LSColorPicker/LSColorPicker.tsx
512
+ import { useEffect as useEffect2, useRef, useState as useState2 } from "react";
513
+ import GradientColorPicker from "react-best-gradient-color-picker";
514
+ import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
515
+ var DEFAULT_COLOR = "#ff4076";
516
+ var LSColorPicker = ({ value = DEFAULT_COLOR, onChange, onBlur, className, name, label, helperText, placeholder, hideGradientControls = false, usePopup = false, disabled = false }) => {
517
+ const isPopupMode = usePopup === true;
518
+ const [open, setOpen] = useState2(false);
519
+ const containerRef = useRef(null);
520
+ const [pickerWidth, setPickerWidth] = useState2(320);
521
+ const showPicker = open;
522
+ const pickerHeight = 220;
523
+ const inlinePickerHeight = hideGradientControls ? pickerHeight + 84 : pickerHeight + 150;
524
+ const pickerContainerStyle = isPopupMode ? {
525
+ position: "absolute",
526
+ right: 0,
527
+ top: "calc(100% + 0.5rem)",
528
+ zIndex: 1e3,
529
+ borderRadius: "0.5rem",
530
+ background: "var(--neutralDark1)",
531
+ padding: "0.5rem",
532
+ boxShadow: "0 8px 24px rgba(0, 0, 0, 0.4)"
533
+ } : {
534
+ position: "static",
535
+ display: "block",
536
+ width: "100%",
537
+ height: inlinePickerHeight,
538
+ minHeight: inlinePickerHeight,
539
+ marginTop: "0.5rem",
540
+ borderRadius: "0.5rem",
541
+ background: "var(--neutralDark1)",
542
+ padding: "0.5rem",
543
+ boxSizing: "border-box",
544
+ overflow: "visible"
545
+ };
546
+ useEffect2(() => {
547
+ const node = containerRef.current;
548
+ if (!node) return void 0;
549
+ const updateWidth = () => {
550
+ const nextWidth = Math.max(node.clientWidth - 16, 220);
551
+ setPickerWidth(nextWidth);
552
+ };
553
+ updateWidth();
554
+ const observer = new ResizeObserver(() => {
555
+ updateWidth();
556
+ });
557
+ observer.observe(node);
558
+ return () => observer.disconnect();
559
+ }, []);
560
+ useEffect2(() => {
561
+ if (!open) return void 0;
562
+ const handleClickOutside = (e) => {
563
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
564
+ setOpen(false);
565
+ }
566
+ };
567
+ document.addEventListener("mousedown", handleClickOutside);
568
+ return () => document.removeEventListener("mousedown", handleClickOutside);
569
+ }, [open]);
570
+ const handleInputChange = (e) => {
571
+ onChange(e.target.value);
572
+ };
573
+ const toggleOpen = () => {
574
+ if (disabled) return;
575
+ setOpen((nextOpen) => !nextOpen);
576
+ };
577
+ return /* @__PURE__ */ jsxs3(
578
+ "div",
579
+ {
580
+ ref: containerRef,
581
+ className: ["ls-color-picker", className].filter(Boolean).join(" "),
582
+ style: {
583
+ position: "relative",
584
+ display: "flex",
585
+ width: "100%",
586
+ flexDirection: "column",
587
+ overflow: "visible"
588
+ },
589
+ children: [
590
+ /* @__PURE__ */ jsx6(
591
+ LSInput,
592
+ {
593
+ className: "w-full",
594
+ name,
595
+ label,
596
+ helperText,
597
+ value,
598
+ onChange: handleInputChange,
599
+ onBlur,
600
+ placeholder,
601
+ disabled,
602
+ endAdornment: /* @__PURE__ */ jsx6(
603
+ "button",
604
+ {
605
+ type: "button",
606
+ className: "relative h-6 w-6 shrink-0 rounded-md border border-white/25 bg-cover bg-center bg-no-repeat p-0 shadow-[0_0_0_1px_rgba(0,0,0,0.25)] disabled:cursor-not-allowed disabled:opacity-50",
607
+ style: { background: value },
608
+ onClick: toggleOpen,
609
+ "aria-label": isPopupMode ? "Open color picker" : "Color preview",
610
+ disabled
611
+ }
612
+ )
613
+ }
614
+ ),
615
+ showPicker && /* @__PURE__ */ jsx6(
616
+ "div",
617
+ {
618
+ className: isPopupMode ? "ls-color-picker__picker ls-color-picker__picker--popup" : "ls-color-picker__picker ls-color-picker__picker--inline",
619
+ style: pickerContainerStyle,
620
+ children: /* @__PURE__ */ jsx6(
621
+ GradientColorPicker,
622
+ {
623
+ hidePresets: true,
624
+ hideColorGuide: true,
625
+ hideAdvancedSliders: true,
626
+ hideInputs: true,
627
+ hideInputType: true,
628
+ hideEyeDrop: false,
629
+ hideGradientControls,
630
+ hideColorTypeBtns: hideGradientControls,
631
+ width: pickerWidth,
632
+ height: pickerHeight,
633
+ className: "[&_circle]:stroke-white [&_polyline]:stroke-white",
634
+ value,
635
+ onChange,
636
+ style: {
637
+ body: { background: "transparent", color: "var(--neutralLight1, #fff)" },
638
+ rbgcpControlBtn: {
639
+ background: "var(--neutralDark4)",
640
+ color: "var(--neutralLight1, #fff)",
641
+ boxShadow: "none"
642
+ },
643
+ rbgcpControlBtnSelected: {
644
+ background: "var(--primary)",
645
+ color: "var(--neutralLight1)",
646
+ boxShadow: "0 6px 14px rgba(255, 64, 118, 0.28)"
647
+ },
648
+ rbgcpControlBtnWrapper: {
649
+ background: "var(--neutralDark4)",
650
+ color: "var(--neutralLight1, #fff)"
651
+ },
652
+ rbgcpControlIconBtn: {
653
+ background: "transparent",
654
+ color: "var(--neutralLight1, #fff)"
655
+ }
656
+ }
657
+ }
658
+ )
659
+ }
660
+ )
661
+ ]
662
+ }
663
+ );
664
+ };
665
+
666
+ // src/components/LSFontPicker/LSFontPicker.tsx
667
+ import { KeyboardArrowDown } from "@mui/icons-material";
668
+ import Autocomplete from "@mui/material/Autocomplete";
669
+ import TextField2 from "@mui/material/TextField";
670
+ import { memo, startTransition, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useState as useState3 } from "react";
671
+ import { jsx as jsx7 } from "react/jsx-runtime";
672
+ var LSFontPicker = memo(function LSFontPicker2({ value, onChange, fonts = [], localFonts = [], onLoadFonts, defaultValue = "Roboto", placeholder = "Select a font", isAlertManager = false, label, helperText }) {
673
+ const AutocompleteComponent = Autocomplete;
674
+ const TextFieldComponent = TextField2;
675
+ const [inputValue, setInputValue] = useState3(value ?? defaultValue);
676
+ const onLoadFontsRef = useRef2(onLoadFonts);
677
+ const onChangeRef = useRef2(onChange);
678
+ const combinedFonts = useMemo2(() => Array.from(/* @__PURE__ */ new Set([...localFonts, ...fonts])).sort(), [fonts, localFonts]);
679
+ const currentValue = value ?? defaultValue;
680
+ useEffect3(() => {
681
+ onLoadFontsRef.current = onLoadFonts;
682
+ onChangeRef.current = onChange;
683
+ }, [onLoadFonts, onChange]);
684
+ useEffect3(() => {
685
+ setInputValue(currentValue);
686
+ }, [currentValue]);
687
+ useEffect3(() => {
688
+ if (!currentValue || isAlertManager) return;
689
+ startTransition(() => {
690
+ onLoadFontsRef.current?.([currentValue]);
691
+ });
692
+ }, [currentValue, isAlertManager]);
693
+ const handleValueChange = (nextValue) => {
694
+ setInputValue(nextValue);
695
+ onChangeRef.current(nextValue);
696
+ if (!nextValue || isAlertManager) return;
697
+ startTransition(() => {
698
+ onLoadFontsRef.current?.([nextValue]);
699
+ });
700
+ };
701
+ return /* @__PURE__ */ jsx7("div", { className: "w-full", children: /* @__PURE__ */ jsx7(
702
+ AutocompleteComponent,
703
+ {
704
+ freeSolo: true,
705
+ disableClearable: true,
706
+ openOnFocus: true,
707
+ forcePopupIcon: true,
708
+ options: combinedFonts,
709
+ value: currentValue,
710
+ inputValue,
711
+ popupIcon: /* @__PURE__ */ jsx7(KeyboardArrowDown, {}),
712
+ isOptionEqualToValue: (option, selectedValue) => option === selectedValue,
713
+ onChange: (_event, newValue) => {
714
+ handleValueChange(typeof newValue === "string" ? newValue : `${newValue ?? ""}`);
715
+ },
716
+ onInputChange: (_event, newInputValue, reason) => {
717
+ if (reason === "input" || reason === "clear") {
718
+ handleValueChange(newInputValue);
719
+ }
720
+ },
721
+ slotProps: {
722
+ popper: {
723
+ sx: { zIndex: 1400 }
724
+ },
725
+ paper: {
726
+ sx: {
727
+ background: "var(--neutralDark3)",
728
+ border: "1px solid var(--neutralDark4)",
729
+ borderRadius: "var(--radiusContainerSm)",
730
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.3)",
731
+ color: "var(--neutralLight1)",
732
+ marginTop: "4px"
733
+ }
734
+ },
735
+ popupIndicator: {
736
+ sx: {
737
+ color: "var(--neutralLight2)",
738
+ "&.MuiAutocomplete-popupIndicatorOpen": {
739
+ transform: "rotate(180deg)"
740
+ }
741
+ }
742
+ }
743
+ },
744
+ ListboxProps: {
745
+ sx: {
746
+ maxHeight: 300,
747
+ padding: 0
748
+ }
749
+ },
750
+ noOptionsText: "No fonts found",
751
+ renderOption: (props, option) => {
752
+ const { key, ...optionProps } = props;
753
+ return /* @__PURE__ */ jsx7(
754
+ "li",
755
+ {
756
+ ...optionProps,
757
+ style: {
758
+ ...optionProps.style ?? {},
759
+ fontFamily: `${option}, Arial, sans-serif`,
760
+ color: "var(--neutralLight1)",
761
+ borderBottom: "1px solid rgba(255, 255, 255, 0.05)",
762
+ padding: "0.75rem 1.25rem",
763
+ transition: "background-color 0.1s ease"
764
+ },
765
+ children: option
766
+ },
767
+ key
768
+ );
769
+ },
770
+ renderInput: (params) => /* @__PURE__ */ jsx7(
771
+ TextFieldComponent,
772
+ {
773
+ ...params,
774
+ label,
775
+ helperText,
776
+ placeholder,
777
+ fullWidth: true,
778
+ className: "mui-ls-input noMinHeight w-full",
779
+ variant: "outlined",
780
+ sx: {
781
+ "& .MuiOutlinedInput-root": {
782
+ paddingRight: "0.5rem"
783
+ }
784
+ },
785
+ InputLabelProps: {
786
+ shrink: true,
787
+ ...params.InputLabelProps ?? {}
788
+ }
789
+ }
790
+ )
791
+ }
792
+ ) });
793
+ });
794
+
795
+ // src/components/LSMultiSelect/LSMultiSelect.tsx
796
+ import { MenuItem } from "@mui/material";
797
+ import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
798
+ var LSMultiSelect = ({ options, placeholder = "Select...", value, onChange, label }) => {
799
+ const handleChange = (event) => {
800
+ const {
801
+ target: { value: value2 }
802
+ } = event;
803
+ onChange(typeof value2 === "string" ? value2.split(",") : value2);
804
+ };
805
+ return /* @__PURE__ */ jsx8(
806
+ LSSelect,
807
+ {
808
+ multiple: true,
809
+ label,
810
+ fullWidth: true,
811
+ className: "mui-multi-select",
812
+ value: value ?? [],
813
+ onChange: handleChange,
814
+ displayEmpty: true,
815
+ renderValue: (selected) => /* @__PURE__ */ jsxs4("div", { className: "flex w-full min-w-0 flex-nowrap items-center justify-between gap-2 overflow-hidden whitespace-nowrap", children: [
816
+ /* @__PURE__ */ jsx8("div", { className: "min-w-0 flex-1 overflow-hidden text-ellipsis whitespace-nowrap", children: selected.length > 0 ? selected.map((val) => options.find((opt) => opt.value === val)?.label ?? val).join(", ") : placeholder }),
817
+ /* @__PURE__ */ jsx8("div", { className: "shrink-0 whitespace-nowrap", children: `(${selected.length})` })
818
+ ] }),
819
+ MenuProps: {
820
+ slotProps: {
821
+ paper: {
822
+ sx: {
823
+ background: "var(--neutralDark2) !important",
824
+ backgroundColor: "var(--neutralDark2)",
825
+ color: "var(--neutralLight1)",
826
+ border: "1px solid var(--neutralDark4)",
827
+ boxShadow: "0 16px 32px rgba(0, 0, 0, 0.32)",
828
+ backdropFilter: "none",
829
+ opacity: 1,
830
+ maxHeight: "280px !important"
831
+ }
832
+ },
833
+ list: {
834
+ sx: {
835
+ backgroundColor: "var(--neutralDark2)",
836
+ color: "var(--neutralLight1)"
837
+ }
838
+ }
839
+ },
840
+ PaperProps: {
841
+ sx: {
842
+ background: "var(--neutralDark2) !important",
843
+ backgroundColor: "var(--neutralDark2)",
844
+ color: "var(--neutralLight1)",
845
+ backdropFilter: "none",
846
+ opacity: 1,
847
+ maxHeight: "280px !important",
848
+ border: "1px solid var(--neutralDark4)",
849
+ "& .MuiList-root": {
850
+ backgroundColor: "var(--neutralDark2)"
851
+ }
852
+ }
853
+ }
854
+ },
855
+ children: options.map((option) => /* @__PURE__ */ jsxs4(
856
+ MenuItem,
857
+ {
858
+ value: option.value,
859
+ sx: {
860
+ display: "flex",
861
+ alignItems: "center",
862
+ gap: "0.4rem",
863
+ color: "var(--neutralLight1)",
864
+ "&.Mui-selected, &.Mui-selected:hover": {
865
+ background: "rgba(255, 64, 118, 0.12)"
866
+ },
867
+ "&:hover": {
868
+ background: "rgba(255, 255, 255, 0.06)"
869
+ }
870
+ },
871
+ children: [
872
+ /* @__PURE__ */ jsx8(LSCheckbox, { checked: (value ?? []).includes(option.value), tabIndex: -1, disableRipple: true }),
873
+ /* @__PURE__ */ jsx8("span", { children: option.label })
874
+ ]
875
+ },
876
+ option.value
877
+ ))
878
+ }
879
+ );
880
+ };
881
+
882
+ // src/components/LSRadio/LSRadio.tsx
883
+ import FormControlLabel2 from "@mui/material/FormControlLabel";
884
+ import Radio from "@mui/material/Radio";
885
+ import RadioGroup from "@mui/material/RadioGroup";
886
+ import classNames4 from "classnames";
887
+ import { jsx as jsx9 } from "react/jsx-runtime";
888
+ var LSRadio = ({ className = "", ...props }) => {
889
+ return /* @__PURE__ */ jsx9(Radio, { ...props, className: classNames4("ls-radio", className) });
890
+ };
891
+ var LSRadioGroup = ({ selections, className = "", optionClassName = "", row, ...props }) => {
892
+ return /* @__PURE__ */ jsx9(RadioGroup, { ...props, row, className: classNames4("ls-radio-group", className, { row }), children: selections.map((selection) => /* @__PURE__ */ jsx9(
893
+ FormControlLabel2,
894
+ {
895
+ className: classNames4("ls-radio-row", optionClassName),
896
+ value: selection.value,
897
+ disabled: selection.disabled,
898
+ control: /* @__PURE__ */ jsx9(LSRadio, {}),
899
+ label: selection.label
900
+ },
901
+ selection.value
902
+ )) });
903
+ };
904
+ LSRadioGroup.displayName = "LSRadioGroup";
905
+
906
+ // src/components/LSTextField/LSTextField.tsx
907
+ import TextField3 from "@mui/material/TextField";
908
+ import { forwardRef as forwardRef3 } from "react";
909
+ import { jsx as jsx10 } from "react/jsx-runtime";
910
+ var LSTextField = forwardRef3((props, ref) => {
911
+ const { InputLabelProps, InputProps, slotProps, ...rest } = props;
912
+ return /* @__PURE__ */ jsx10(
913
+ TextField3,
914
+ {
915
+ ...rest,
916
+ variant: "outlined",
917
+ slotProps: {
918
+ ...slotProps ?? {},
919
+ input: {
920
+ ...slotProps?.input ?? {},
921
+ ...InputProps ?? {},
922
+ sx: {
923
+ ...slotProps?.input?.sx ?? {},
924
+ ...InputProps?.sx ?? {}
925
+ }
926
+ },
927
+ inputLabel: {
928
+ ...slotProps?.inputLabel ?? {},
929
+ shrink: true,
930
+ ...InputLabelProps ?? {}
931
+ }
932
+ },
933
+ ref
934
+ }
935
+ );
936
+ });
937
+ LSTextField.displayName = "LSTextField";
938
+
939
+ // src/components/LSVariableInputField/LSVariableInputField.tsx
940
+ import Autocomplete2, { createFilterOptions } from "@mui/material/Autocomplete";
941
+ import InputAdornment2 from "@mui/material/InputAdornment";
942
+ import Popover from "@mui/material/Popover";
943
+ import { createContext, forwardRef as forwardRef4, useCallback as useCallback2, useContext, useEffect as useEffect4, useMemo as useMemo3, useRef as useRef3, useState as useState4 } from "react";
944
+ import { Fragment, jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
945
+ var LSVariableInputContext = createContext({});
946
+ var LSVariableInputProvider = ({ children, value }) => {
947
+ return /* @__PURE__ */ jsx11(LSVariableInputContext.Provider, { value, children });
948
+ };
949
+ var DEFAULT_FUNCTION_VARIABLES = [
950
+ "sum_variables",
951
+ "offset_count",
952
+ "read_file",
953
+ "read_url",
954
+ "selection",
955
+ "random",
956
+ "random_input",
957
+ "get_commands",
958
+ "get_all_commands",
959
+ "convert_color_to_hex",
960
+ "get_latest_file_from_folder",
961
+ "get_random_file_from_folder",
962
+ "screenshot",
963
+ "overlay_screenshot",
964
+ "obs_screenshot",
965
+ "obs_replay",
966
+ "obs_vertical_replay",
967
+ "get_queue_count",
968
+ "lumia_uptime",
969
+ "twitch_uptime",
970
+ "youtube_uptime",
971
+ "facebook_uptime",
972
+ "twitch_followage",
973
+ "twitch_next_ad",
974
+ "twitch_get_avatar",
975
+ "get_var_from_msg",
976
+ "get_user_loyalty_points",
977
+ "translate",
978
+ "ai_prompt",
979
+ "viewer_profile_summary"
980
+ ];
981
+ var filter = createFilterOptions();
982
+ var isNully = (value) => value === null || value === void 0;
983
+ var defaultTranslate = (key, fallback, options) => {
984
+ if (fallback && fallback !== "-") return fallback;
985
+ if (key === "overlay-variables.variables-description") return "Use variables that will automatically be replaced before sending out the text";
986
+ if (key === "overlay-variables.variable") return "Variable";
987
+ if (key === "overlay-variables.description") return "Description";
988
+ if (key === "assets.search") return "Search";
989
+ if (key === "variables.functionvariables") return "Function variables";
990
+ if (key.startsWith("variables.")) {
991
+ const variableName = key.replace("variables.", "");
992
+ const example = options?.example;
993
+ return example === void 0 || example === null ? variableName : String(example);
994
+ }
995
+ return fallback ?? key;
996
+ };
997
+ var normalizeAllowedDefinitions = (allowedVariables) => {
998
+ if (!Array.isArray(allowedVariables)) return [];
999
+ const unique = /* @__PURE__ */ new Set();
1000
+ const definitions = [];
1001
+ allowedVariables.forEach((variable) => {
1002
+ let variableName = "";
1003
+ let description;
1004
+ if (typeof variable === "string") {
1005
+ variableName = variable.trim();
1006
+ } else if (variable && typeof variable === "object") {
1007
+ const typedVariable = variable;
1008
+ const candidateName = [typedVariable.name, typedVariable.key, typedVariable.variable].find((value) => typeof value === "string");
1009
+ variableName = typeof candidateName === "string" ? candidateName.trim() : "";
1010
+ description = typeof typedVariable.description === "string" ? typedVariable.description.trim() : void 0;
1011
+ }
1012
+ if (!variableName || unique.has(variableName)) return;
1013
+ unique.add(variableName);
1014
+ definitions.push({ name: variableName, description });
1015
+ });
1016
+ return definitions;
1017
+ };
1018
+ var LSVariableInputField = forwardRef4((props, ref) => {
1019
+ const context = useContext(LSVariableInputContext);
1020
+ const {
1021
+ name,
1022
+ label,
1023
+ type,
1024
+ isAutoComplete,
1025
+ autoCompleteOptions,
1026
+ renderOption,
1027
+ hideVariables,
1028
+ allowedVariables,
1029
+ disabled,
1030
+ autoFocus,
1031
+ inputProps = {},
1032
+ multiline,
1033
+ rows,
1034
+ maxRows,
1035
+ value,
1036
+ placeholder,
1037
+ variant,
1038
+ ListboxComponent,
1039
+ onScrollListBox,
1040
+ onHighlightChange,
1041
+ onPopupClose,
1042
+ onPopupOpen,
1043
+ afterFilter,
1044
+ onChange,
1045
+ systemVariables: systemVariablesProp,
1046
+ functionVariables: functionVariablesProp,
1047
+ translate,
1048
+ onVariableTranslationsNeeded
1049
+ } = props;
1050
+ const t = translate ?? context.translate ?? defaultTranslate;
1051
+ const systemVariables = systemVariablesProp ?? context.systemVariables ?? {};
1052
+ const functionVariables = useMemo3(() => functionVariablesProp ?? context.functionVariables ?? DEFAULT_FUNCTION_VARIABLES, [context.functionVariables, functionVariablesProp]);
1053
+ const requestTranslations = onVariableTranslationsNeeded ?? context.onVariableTranslationsNeeded;
1054
+ const containerRef = useRef3(null);
1055
+ const variableId = useRef3(`variable-input-${name ?? "field"}`);
1056
+ const [showVariables, setShowVariables] = useState4(false);
1057
+ const [searchQuery, setSearchQuery] = useState4("");
1058
+ const functionVariableSet = useMemo3(() => new Set(functionVariables), [functionVariables]);
1059
+ const allowedVariableDefinitions = useMemo3(() => normalizeAllowedDefinitions(allowedVariables), [allowedVariables]);
1060
+ const allowedVariableDefinitionLookup = useMemo3(() => {
1061
+ const lookup = /* @__PURE__ */ new Map();
1062
+ allowedVariableDefinitions.forEach((definition) => lookup.set(definition.name, definition));
1063
+ return lookup;
1064
+ }, [allowedVariableDefinitions]);
1065
+ const allowedVariableNames = useMemo3(() => allowedVariableDefinitions.map((definition) => definition.name), [allowedVariableDefinitions]);
1066
+ const [filteredAllowedVariables, setFilteredAllowedVariables] = useState4(allowedVariableNames);
1067
+ const [filteredSystemVariables, setFilteredSystemVariables] = useState4([]);
1068
+ useEffect4(() => {
1069
+ requestTranslations?.();
1070
+ }, [requestTranslations]);
1071
+ const getVariableVisualType = useCallback2(
1072
+ (variableName) => {
1073
+ if (functionVariableSet.has(variableName)) return "func";
1074
+ return !isNully(systemVariables?.[variableName]) ? "system" : "custom";
1075
+ },
1076
+ [functionVariableSet, systemVariables]
1077
+ );
1078
+ const getVariableTypeSortRank = (variableType) => {
1079
+ if (variableType === "custom") return 0;
1080
+ if (variableType === "func") return 1;
1081
+ return 2;
1082
+ };
1083
+ const orderByType = useCallback2(
1084
+ (variableNames) => {
1085
+ const grouped = { custom: [], func: [], system: [] };
1086
+ variableNames.forEach((variableName) => {
1087
+ grouped[getVariableVisualType(variableName)].push(variableName);
1088
+ });
1089
+ return [...grouped.custom, ...grouped.func, ...grouped.system];
1090
+ },
1091
+ [getVariableVisualType]
1092
+ );
1093
+ const sortByTypeThenName = useCallback2(
1094
+ (variableNames) => [...variableNames].sort((a, b) => {
1095
+ const typeDiff = getVariableTypeSortRank(getVariableVisualType(a)) - getVariableTypeSortRank(getVariableVisualType(b));
1096
+ return typeDiff !== 0 ? typeDiff : a.localeCompare(b);
1097
+ }),
1098
+ [getVariableVisualType]
1099
+ );
1100
+ const getAllowedVariableDescription = useCallback2(
1101
+ (variableName) => {
1102
+ const fromDefinitions = allowedVariableDefinitionLookup.get(variableName)?.description;
1103
+ if (fromDefinitions) return fromDefinitions;
1104
+ const translationKey = `variables.${variableName}`;
1105
+ const translated = t(translationKey, variableName);
1106
+ return translated && translated !== translationKey ? translated : variableName;
1107
+ },
1108
+ [allowedVariableDefinitionLookup, t]
1109
+ );
1110
+ const filterBasedOnQuery = useCallback2(() => {
1111
+ const query = (searchQuery ?? "").toLowerCase().replace("{{", "").replace("}}", "").trim();
1112
+ if (allowedVariableNames.length > 0) {
1113
+ if (!query) {
1114
+ setFilteredAllowedVariables(orderByType(allowedVariableNames));
1115
+ } else {
1116
+ const nameMatches = [];
1117
+ const descMatches = [];
1118
+ allowedVariableNames.forEach((variable) => {
1119
+ const nameLower = variable?.toLowerCase();
1120
+ const descLower = getAllowedVariableDescription(variable)?.toLowerCase();
1121
+ if (nameLower?.includes(query)) nameMatches.push(variable);
1122
+ else if (descLower?.includes(query)) descMatches.push(variable);
1123
+ });
1124
+ setFilteredAllowedVariables([...sortByTypeThenName(nameMatches), ...sortByTypeThenName(descMatches)]);
1125
+ }
1126
+ } else {
1127
+ setFilteredAllowedVariables([]);
1128
+ }
1129
+ const systemKeys = Object.keys(systemVariables ?? {}).filter((variableKey) => !isNully(systemVariables?.[variableKey]));
1130
+ const allowedVariableSet = new Set(allowedVariableNames);
1131
+ const candidates = [...functionVariables, ...systemKeys].filter((variableKey, idx, list) => list.indexOf(variableKey) === idx && !allowedVariableSet.has(variableKey));
1132
+ if (!query) {
1133
+ setFilteredSystemVariables(orderByType(candidates));
1134
+ } else {
1135
+ const nameMatches = [];
1136
+ const descMatches = [];
1137
+ candidates.forEach((key) => {
1138
+ const nameLower = key?.toLowerCase();
1139
+ const descStr = t(`variables.${key}`, "-", {
1140
+ example: systemVariables[key],
1141
+ interpolation: { escapeValue: false, prefix: "{{{", suffix: "}}}" }
1142
+ });
1143
+ const descLower = descStr?.toLowerCase();
1144
+ if (nameLower?.includes(query)) nameMatches.push(key);
1145
+ else if (descLower?.includes(query)) descMatches.push(key);
1146
+ });
1147
+ setFilteredSystemVariables([...sortByTypeThenName(nameMatches), ...sortByTypeThenName(descMatches)]);
1148
+ }
1149
+ }, [allowedVariableNames, functionVariables, getAllowedVariableDescription, orderByType, searchQuery, sortByTypeThenName, systemVariables, t]);
1150
+ useEffect4(() => {
1151
+ filterBasedOnQuery();
1152
+ }, [filterBasedOnQuery]);
1153
+ const clickedVariableIcon = () => {
1154
+ if (!hideVariables) setShowVariables((current) => !current);
1155
+ };
1156
+ const appendValue = (newValue) => {
1157
+ const currentValue = Array.isArray(value) ? value.join("") : value;
1158
+ onChange?.(currentValue ? `${currentValue}${newValue}` : newValue);
1159
+ };
1160
+ const insertVariable = (variable) => {
1161
+ appendValue(`{{${variable}}}`);
1162
+ };
1163
+ const getVariableColorClass = (variableType, isSuggested = false) => {
1164
+ if (isSuggested && variableType !== "func") return "text-[var(--customVariables,#69ffd2)]";
1165
+ if (variableType === "func") return "text-[var(--functionVariables,var(--semanticPurple,#b489ff))]";
1166
+ if (variableType === "system") return "text-[var(--normalVariables,var(--semanticBlue,#65b8ff))]";
1167
+ return "text-[var(--customVariables,#69ffd2)]";
1168
+ };
1169
+ const renderVariableToken = (variableName, variableType, isSuggested = false) => /* @__PURE__ */ jsxs5("div", { className: `flex min-w-0 items-center ${getVariableColorClass(variableType, isSuggested)}`, children: [
1170
+ /* @__PURE__ */ jsx11("span", { className: "min-w-0 break-all", children: `{{${variableName}}}` }),
1171
+ variableType === "func" && /* @__PURE__ */ jsx11("span", { className: "ml-2 inline-flex shrink-0 items-center rounded border border-current px-1 py-0 text-[10px] font-semibold uppercase leading-none", title: t("variables.functionvariables", "Function variables"), children: "fx" })
1172
+ ] });
1173
+ const handleFilterOptions = (options, params) => {
1174
+ const filtered = filter(options, params);
1175
+ afterFilter?.(filtered);
1176
+ return filtered;
1177
+ };
1178
+ const textField = (params = {}) => /* @__PURE__ */ jsx11(
1179
+ VariableInputTextField,
1180
+ {
1181
+ params,
1182
+ id: variableId.current,
1183
+ containerRef,
1184
+ name,
1185
+ label,
1186
+ type,
1187
+ variant,
1188
+ disabled,
1189
+ autoFocus,
1190
+ multiline,
1191
+ placeholder,
1192
+ rows,
1193
+ maxRows,
1194
+ value,
1195
+ onChange,
1196
+ clickedVariableIcon,
1197
+ inputProps,
1198
+ ref
1199
+ }
1200
+ );
1201
+ return /* @__PURE__ */ jsxs5(Fragment, { children: [
1202
+ /* @__PURE__ */ jsx11(
1203
+ Popover,
1204
+ {
1205
+ anchorEl: containerRef.current,
1206
+ anchorOrigin: { vertical: "bottom", horizontal: "right" },
1207
+ transformOrigin: { vertical: "top", horizontal: "right" },
1208
+ open: !hideVariables && showVariables,
1209
+ onClose: clickedVariableIcon,
1210
+ slotProps: {
1211
+ paper: {
1212
+ sx: {
1213
+ color: "var(--neutralLight2, #cac9d5)",
1214
+ backgroundColor: "var(--neutralDark1, #171628)",
1215
+ padding: 1,
1216
+ border: "1px solid var(--neutralDark4, #393853)"
1217
+ }
1218
+ }
1219
+ },
1220
+ children: /* @__PURE__ */ jsxs5("div", { className: "flex max-h-[55vh] min-h-[50vh] w-[92vw] max-w-[1100px] flex-col overflow-hidden [--variable-custom-color:var(--customVariables,#69ffd2)] [--variable-function-color:var(--functionVariables,var(--semanticPurple,#b489ff))] [--variable-normal-color:var(--normalVariables,var(--semanticBlue,#65b8ff))]", children: [
1221
+ /* @__PURE__ */ jsxs5("div", { className: "mb-2.5 text-[var(--neutralLight2,#cac9d5)]", children: [
1222
+ /* @__PURE__ */ jsx11("div", { children: t("overlay-variables.variables-description", "Use variables that will automatically be replaced before sending out the text") }),
1223
+ /* @__PURE__ */ jsx11(
1224
+ LSInput,
1225
+ {
1226
+ autoFocus: true,
1227
+ startAdornment: /* @__PURE__ */ jsx11("span", { className: "mr-2.5 inline-flex h-[18px] w-[18px] items-center justify-center", children: "\u2315" }),
1228
+ placeholder: t("assets.search", "Search"),
1229
+ value: searchQuery,
1230
+ onChange: (e) => setSearchQuery(e.target.value),
1231
+ type: "text",
1232
+ style: { padding: "1rem 0" }
1233
+ }
1234
+ )
1235
+ ] }),
1236
+ /* @__PURE__ */ jsxs5("div", { className: "mb-1 grid grid-cols-[minmax(300px,1.5fr)_2fr] text-[var(--neutralLight3,#9392a1)]", children: [
1237
+ /* @__PURE__ */ jsx11("div", { children: t("overlay-variables.variable", "Variable") }),
1238
+ /* @__PURE__ */ jsx11("div", { children: t("overlay-variables.description", "Description") })
1239
+ ] }),
1240
+ /* @__PURE__ */ jsxs5("div", { className: "h-full overflow-auto pr-4", children: [
1241
+ allowedVariableNames.length > 0 && filteredAllowedVariables?.map((variableName) => /* @__PURE__ */ jsxs5("div", { className: "grid cursor-pointer grid-cols-[minmax(300px,1.5fr)_2fr] gap-4 border-b border-[var(--neutralLight3,#9392a1)] py-[18px] active:opacity-80", onClick: () => insertVariable(variableName), children: [
1242
+ renderVariableToken(variableName, getVariableVisualType(variableName), true),
1243
+ /* @__PURE__ */ jsx11("div", { className: "max-w-[600px] break-words", children: getAllowedVariableDescription(variableName) })
1244
+ ] }, variableName)),
1245
+ filteredSystemVariables?.map((variableKey) => /* @__PURE__ */ jsxs5("div", { className: "grid cursor-pointer grid-cols-[minmax(300px,1.5fr)_2fr] gap-4 border-b border-[var(--neutralLight3,#9392a1)] py-[18px] active:opacity-80", onClick: () => insertVariable(variableKey), children: [
1246
+ renderVariableToken(variableKey, getVariableVisualType(variableKey)),
1247
+ /* @__PURE__ */ jsx11("div", { className: "max-w-[600px] break-words", children: t(`variables.${variableKey}`, "-", { example: systemVariables?.[variableKey], interpolation: { escapeValue: false, prefix: "{{{", suffix: "}}}" } }) })
1248
+ ] }, variableKey))
1249
+ ] })
1250
+ ] })
1251
+ }
1252
+ ),
1253
+ isAutoComplete ? /* @__PURE__ */ jsx11(
1254
+ Autocomplete2,
1255
+ {
1256
+ disableClearable: true,
1257
+ freeSolo: true,
1258
+ includeInputInList: true,
1259
+ onChange: (_e, nextValue) => onChange?.(nextValue?.value ?? nextValue),
1260
+ onInputChange: (_e, nextValue) => onChange?.(nextValue),
1261
+ options: autoCompleteOptions ?? [],
1262
+ value,
1263
+ renderOption,
1264
+ getOptionLabel: (option) => typeof option === "string" ? option : option.label,
1265
+ filterOptions: handleFilterOptions,
1266
+ slots: { listbox: ListboxComponent },
1267
+ slotProps: { listbox: { onScroll: onScrollListBox } },
1268
+ onHighlightChange,
1269
+ onOpen: onPopupOpen,
1270
+ onClose: onPopupClose,
1271
+ renderInput: (params) => textField(params)
1272
+ }
1273
+ ) : textField()
1274
+ ] });
1275
+ });
1276
+ LSVariableInputField.displayName = "LSVariableInputField";
1277
+ var VariableInputTextField = forwardRef4(
1278
+ ({ id, name, label, type, variant, disabled, autoFocus, multiline, placeholder, rows, maxRows, value, onChange, inputProps, clickedVariableIcon, params = {}, containerRef }, ref) => {
1279
+ return /* @__PURE__ */ jsx11(
1280
+ LSTextField,
1281
+ {
1282
+ id,
1283
+ name,
1284
+ label,
1285
+ type,
1286
+ color: "secondary",
1287
+ variant,
1288
+ disabled,
1289
+ autoFocus,
1290
+ multiline,
1291
+ placeholder,
1292
+ rows,
1293
+ maxRows,
1294
+ value,
1295
+ fullWidth: true,
1296
+ className: `mui-ls-input noMinHeight ${params?.className ?? ""} ${inputProps?.className ?? ""}`.trim(),
1297
+ onChange: (e) => onChange?.(e.target.value),
1298
+ ...inputProps,
1299
+ ...params,
1300
+ InputProps: {
1301
+ ...params?.InputProps ?? {},
1302
+ ...inputProps?.InputProps ?? {},
1303
+ endAdornment: /* @__PURE__ */ jsxs5(Fragment, { children: [
1304
+ params?.slotProps?.input?.endAdornment ?? params?.InputProps?.endAdornment ?? null,
1305
+ /* @__PURE__ */ jsx11(
1306
+ InputAdornment2,
1307
+ {
1308
+ position: "end",
1309
+ onClick: clickedVariableIcon,
1310
+ ref: containerRef,
1311
+ className: "cursor-pointer",
1312
+ sx: {
1313
+ cursor: "pointer",
1314
+ background: "var(--primary)",
1315
+ borderRadius: "50%",
1316
+ display: "flex",
1317
+ alignItems: "center",
1318
+ justifyContent: "center",
1319
+ padding: "4px",
1320
+ minWidth: "22px",
1321
+ minHeight: "22px",
1322
+ width: "22px",
1323
+ height: "22px",
1324
+ color: "var(--neutralDark1)",
1325
+ "& *": {
1326
+ cursor: "pointer",
1327
+ color: "var(--neutralDark1)"
1328
+ }
1329
+ },
1330
+ children: "{}"
1331
+ }
1332
+ )
1333
+ ] })
1334
+ },
1335
+ ref
1336
+ }
1337
+ );
1338
+ }
1339
+ );
1340
+ VariableInputTextField.displayName = "VariableInputTextField";
1341
+
52
1342
  // src/utils/variableCompletionOptions.ts
53
1343
  function variableCompletionOptions(context, variables) {
54
1344
  const before = context.state.sliceDoc(0, context.pos);
@@ -265,8 +1555,631 @@ var codeMirrorlinterOptions = (type, language = "js") => {
265
1555
  }
266
1556
  return jsOptions;
267
1557
  };
1558
+
1559
+ // src/utils/chatMedia.ts
1560
+ var URL_TOKEN_REGEX = /(?:https?:\/\/|www\.)[^\s<]+/gi;
1561
+ var TRAILING_LINK_PUNCTUATION_REGEX = /[),.!?;:'"]+$/;
1562
+ var MEDIA_IMAGE_REGEX = /\.(gif|png|jpe?g|webp|bmp|avif)(?:[?#].*)?$/i;
1563
+ var MEDIA_VIDEO_REGEX = /\.(mp4|webm|mov|m4v)(?:[?#].*)?$/i;
1564
+ var MEDIA_AUDIO_REGEX = /\.(mp3|wav|ogg|oga|aac|m4a|flac|opus)(?:[?#].*)?$/i;
1565
+ var YOUTUBE_ID_REGEX = /^[a-zA-Z0-9_-]{6,}$/;
1566
+ var SPOTIFY_EMBED_TYPES = /* @__PURE__ */ new Set(["track", "album", "playlist", "episode", "show", "artist"]);
1567
+ var MEDIA_PREVIEW_USER_LEVEL_VALUES = ["streamer", "moderators", "vips", "tier3", "tier2", "subscribers", "regular", "follower", "anyone"];
1568
+ var parseMessageLinks = (value) => {
1569
+ if (!value) {
1570
+ return [{ text: "" }];
1571
+ }
1572
+ const parts = [];
1573
+ let cursor = 0;
1574
+ for (const match of value.matchAll(URL_TOKEN_REGEX)) {
1575
+ const rawToken = match[0];
1576
+ if (!rawToken) {
1577
+ continue;
1578
+ }
1579
+ const start = match.index ?? 0;
1580
+ const end = start + rawToken.length;
1581
+ if (start > cursor) {
1582
+ parts.push({ text: value.slice(cursor, start) });
1583
+ }
1584
+ const trailing = rawToken.match(TRAILING_LINK_PUNCTUATION_REGEX)?.[0] ?? "";
1585
+ const cleaned = trailing ? rawToken.slice(0, -trailing.length) : rawToken;
1586
+ if (cleaned) {
1587
+ const href = cleaned.startsWith("http://") || cleaned.startsWith("https://") ? cleaned : `https://${cleaned}`;
1588
+ parts.push({ text: cleaned, url: href });
1589
+ } else {
1590
+ parts.push({ text: rawToken });
1591
+ }
1592
+ if (trailing) {
1593
+ parts.push({ text: trailing });
1594
+ }
1595
+ cursor = end;
1596
+ }
1597
+ if (cursor < value.length) {
1598
+ parts.push({ text: value.slice(cursor) });
1599
+ }
1600
+ return parts.length ? parts : [{ text: value }];
1601
+ };
1602
+ var tokenizeChatMessage = (value, options) => {
1603
+ const hyperClickableLinks = options?.hyperClickableLinks !== false;
1604
+ const previewMediaInChat = options?.previewMediaInChat !== false;
1605
+ if (!value) {
1606
+ return [{ type: "text", text: "" }];
1607
+ }
1608
+ if (!hyperClickableLinks && !previewMediaInChat) {
1609
+ return [{ type: "text", text: value }];
1610
+ }
1611
+ const parts = parseMessageLinks(value);
1612
+ const tokens = [];
1613
+ for (const part of parts) {
1614
+ if (!part.url) {
1615
+ tokens.push({ type: "text", text: part.text });
1616
+ continue;
1617
+ }
1618
+ const media = previewMediaInChat ? getMediaPreviewFromUrl(part.url) : null;
1619
+ if (media) {
1620
+ tokens.push({
1621
+ type: "media",
1622
+ text: part.text,
1623
+ url: part.url,
1624
+ media
1625
+ });
1626
+ continue;
1627
+ }
1628
+ if (hyperClickableLinks) {
1629
+ tokens.push({
1630
+ type: "link",
1631
+ text: part.text,
1632
+ url: part.url
1633
+ });
1634
+ continue;
1635
+ }
1636
+ tokens.push({ type: "text", text: part.text });
1637
+ }
1638
+ return tokens.length ? tokens : [{ type: "text", text: value }];
1639
+ };
1640
+ var buildChatMessageContent = ({
1641
+ message,
1642
+ replaceWord,
1643
+ filteredWordsRegex,
1644
+ emotesRaw,
1645
+ emotesPack,
1646
+ origin,
1647
+ emoteParserType,
1648
+ isCheer,
1649
+ storeEmotes,
1650
+ youtubeEmotes,
1651
+ allowParserTypes
1652
+ }) => {
1653
+ let normalizedMessage = message ?? "";
1654
+ if (filteredWordsRegex && typeof replaceWord === "string") {
1655
+ normalizedMessage = normalizedMessage.replaceAll(filteredWordsRegex, replaceWord);
1656
+ }
1657
+ const arrFromMsg = Array.from(normalizedMessage);
1658
+ const parserType = emoteParserType || origin;
1659
+ const allowParserType = !allowParserTypes || allowParserTypes.includes(parserType ?? "");
1660
+ const emotes = [];
1661
+ const parsePluginEmotesRaw = (raw) => {
1662
+ const text = raw?.trim?.();
1663
+ if (!text || text[0] !== "[" && text[0] !== "{") {
1664
+ return [];
1665
+ }
1666
+ let parsed;
1667
+ try {
1668
+ parsed = JSON.parse(text);
1669
+ } catch {
1670
+ return [];
1671
+ }
1672
+ const items = Array.isArray(parsed) ? parsed : Array.isArray(parsed?.emotes) ? parsed.emotes : [];
1673
+ if (!items.length) {
1674
+ return [];
1675
+ }
1676
+ return items.map((item) => {
1677
+ const rawStart = Number(item?.start);
1678
+ const rawEnd = Number(item?.end);
1679
+ const directUrls = Array.isArray(item?.urls) ? item.urls.filter((url2) => typeof url2 === "string" && url2) : [];
1680
+ const url = typeof item?.url === "string" ? item.url : "";
1681
+ const urls = directUrls.length ? directUrls : url ? [url] : [];
1682
+ if (!urls.length || !Number.isFinite(rawStart) || !Number.isFinite(rawEnd)) {
1683
+ return null;
1684
+ }
1685
+ let start = Math.max(0, Math.floor(rawStart));
1686
+ let end = Math.min(Math.floor(rawEnd) + 1, arrFromMsg.length);
1687
+ if (start > 0 && arrFromMsg[start - 1] === ":") {
1688
+ start -= 1;
1689
+ }
1690
+ if (end < arrFromMsg.length && arrFromMsg[end] === ":") {
1691
+ end += 1;
1692
+ }
1693
+ if (end <= start) {
1694
+ return null;
1695
+ }
1696
+ return {
1697
+ id: item?.id || `${start}-${end}`,
1698
+ urls,
1699
+ start,
1700
+ end
1701
+ };
1702
+ }).filter(Boolean);
1703
+ };
1704
+ const pluginRawEmotes = emotesRaw ? parsePluginEmotesRaw(emotesRaw) : [];
1705
+ if (pluginRawEmotes.length) {
1706
+ emotes.push(...pluginRawEmotes);
1707
+ }
1708
+ if (allowParserType && emotesRaw && !pluginRawEmotes.length && parserType === "twitch") {
1709
+ for (const emote of emotesRaw.split("/")) {
1710
+ if (!emote) continue;
1711
+ const [emoteId, indicies] = emote.split(":");
1712
+ if (!emoteId || !indicies) continue;
1713
+ for (const indexSet of indicies.split(",")) {
1714
+ const [start, end] = indexSet.split("-");
1715
+ if (start === void 0 || end === void 0) continue;
1716
+ emotes.push({
1717
+ id: emoteId,
1718
+ urls: [
1719
+ `https://static-cdn.jtvnw.net/emoticons/v2/${emoteId}/default/dark/1.0`,
1720
+ `https://static-cdn.jtvnw.net/emoticons/v2/${emoteId}/default/dark/2.0`,
1721
+ `https://static-cdn.jtvnw.net/emoticons/v2/${emoteId}/default/dark/3.0`
1722
+ ],
1723
+ start: Math.max(+start, 0),
1724
+ end: Math.min(+end + 1, normalizedMessage.length)
1725
+ });
1726
+ }
1727
+ }
1728
+ } else if (allowParserType && emotesPack && parserType === "kick") {
1729
+ const emotesPackRecord = emotesPack;
1730
+ Object.keys(emotesPackRecord).forEach((emoteId) => {
1731
+ emotesPackRecord[emoteId]?.locations?.forEach((location) => {
1732
+ const [start, end] = location.split("-");
1733
+ if (start === void 0 || end === void 0) return;
1734
+ let url;
1735
+ if (emotesPackRecord[emoteId]?.type === "emote") {
1736
+ url = `https://files.kick.com/emotes/${emoteId}/fullsize`;
1737
+ } else {
1738
+ url = `https://dbxmjjzl5pc1g.cloudfront.net/1065f255-473b-4a4d-a383-1282aa1ab9d5/images/emojis/${emoteId}.png`;
1739
+ }
1740
+ if (url) {
1741
+ emotes.push({
1742
+ id: emoteId,
1743
+ urls: [url],
1744
+ start: Math.max(+start, 0),
1745
+ end: Math.min(+end + 1, normalizedMessage.length)
1746
+ });
1747
+ }
1748
+ });
1749
+ });
1750
+ } else if (allowParserType && emotesPack && parserType === "discord") {
1751
+ const emotesPackRecord = emotesPack;
1752
+ Object.keys(emotesPackRecord).forEach((emoteId) => {
1753
+ emotesPackRecord[emoteId]?.locations?.forEach((location) => {
1754
+ const [start, end] = location.split("-");
1755
+ if (start === void 0 || end === void 0) return;
1756
+ const url = `https://cdn.discordapp.com/emojis/${emoteId}`;
1757
+ emotes.push({
1758
+ id: emoteId,
1759
+ urls: [url],
1760
+ start: Math.max(+start, 0),
1761
+ end: Math.min(+end + 1, normalizedMessage.length)
1762
+ });
1763
+ });
1764
+ });
1765
+ }
1766
+ let idx = -1;
1767
+ let nextIdx = 0;
1768
+ const separator = origin === "youtube" ? ":" : " ";
1769
+ do {
1770
+ nextIdx = arrFromMsg.indexOf(separator, idx + 1);
1771
+ if (nextIdx === -1) {
1772
+ nextIdx = arrFromMsg.length;
1773
+ }
1774
+ const emote = arrFromMsg.slice(idx + 1, nextIdx).join("");
1775
+ const start = idx + 1;
1776
+ const end = nextIdx;
1777
+ if (emote) {
1778
+ if (storeEmotes?.ffz?.[emote]) {
1779
+ emotes.push({
1780
+ id: emote,
1781
+ urls: [storeEmotes.ffz[emote]],
1782
+ start,
1783
+ end
1784
+ });
1785
+ } else if (storeEmotes?.bttv?.[emote]) {
1786
+ emotes.push({
1787
+ id: emote,
1788
+ urls: [storeEmotes.bttv[emote]],
1789
+ start,
1790
+ end
1791
+ });
1792
+ } else if (storeEmotes?.seventv?.[emote]) {
1793
+ emotes.push({
1794
+ id: emote,
1795
+ urls: [storeEmotes.seventv[emote]],
1796
+ start,
1797
+ end
1798
+ });
1799
+ } else if (youtubeEmotes?.[emote]) {
1800
+ emotes.push({
1801
+ id: emote,
1802
+ urls: [youtubeEmotes[emote]],
1803
+ start,
1804
+ end
1805
+ });
1806
+ } else if (isCheer && /[a-z]+\d+/gi.exec(emote)) {
1807
+ const cheerAmount = parseInt(emote.replace(/^\D+/g, ""));
1808
+ let roundedAmount = 1;
1809
+ let bitColor = "#979797";
1810
+ if (cheerAmount >= 1e4) {
1811
+ roundedAmount = 1e4;
1812
+ bitColor = "#f43021";
1813
+ } else if (cheerAmount >= 5e3) {
1814
+ roundedAmount = 5e3;
1815
+ bitColor = "#0099fe";
1816
+ } else if (cheerAmount >= 1e3) {
1817
+ roundedAmount = 1e3;
1818
+ bitColor = "#1db2a5";
1819
+ } else if (cheerAmount >= 100) {
1820
+ roundedAmount = 100;
1821
+ bitColor = "#9c3ee8";
1822
+ }
1823
+ emotes.push({
1824
+ id: emote,
1825
+ type: "cheer",
1826
+ roundedAmount,
1827
+ cheerAmount,
1828
+ bitColor,
1829
+ start,
1830
+ end
1831
+ });
1832
+ }
1833
+ }
1834
+ } while ((idx = arrFromMsg.indexOf(separator, nextIdx)) !== -1);
1835
+ emotes.sort((x, y) => x.start - y.start);
1836
+ let index = 0;
1837
+ const content = [];
1838
+ for (const emote of emotes) {
1839
+ const slicedMsg = arrFromMsg.slice(index, emote.start).join("");
1840
+ content.push(origin === "youtube" ? slicedMsg?.replaceAll(":", "") : slicedMsg);
1841
+ if ("type" in emote && emote.type === "cheer") {
1842
+ content.push({
1843
+ id: emote.id,
1844
+ type: "cheer",
1845
+ roundedAmount: emote.roundedAmount,
1846
+ cheerAmount: emote.cheerAmount,
1847
+ bitColor: emote.bitColor,
1848
+ key: `${emote.start}-${emote.end}`
1849
+ });
1850
+ } else if ("urls" in emote) {
1851
+ content.push({
1852
+ id: emote.id,
1853
+ urls: emote.urls,
1854
+ key: `${emote.start}-${emote.end}`
1855
+ });
1856
+ }
1857
+ index = emote.end;
1858
+ }
1859
+ const subStrMsg = arrFromMsg.slice(index, arrFromMsg.length).join("");
1860
+ content.push(origin === "youtube" ? subStrMsg?.replaceAll(":", "") : subStrMsg);
1861
+ return content;
1862
+ };
1863
+ var resolveMediaPreviewSetting = (value, fallback) => {
1864
+ return typeof value === "boolean" ? value : fallback;
1865
+ };
1866
+ var normalizeMediaPreviewUserLevels = (value) => {
1867
+ if (Array.isArray(value)) {
1868
+ const normalized = value.map((level) => String(level).trim().toLowerCase()).filter((level) => MEDIA_PREVIEW_USER_LEVEL_VALUES.includes(level));
1869
+ return [...new Set(normalized)];
1870
+ }
1871
+ if (typeof value === "string") {
1872
+ const normalized = value.split(",").map((level) => level.trim().toLowerCase()).filter((level) => MEDIA_PREVIEW_USER_LEVEL_VALUES.includes(level));
1873
+ return [...new Set(normalized)];
1874
+ }
1875
+ return [];
1876
+ };
1877
+ var resolveMediaPreviewRoleSettings = (settings) => {
1878
+ if (Array.isArray(settings.previewMediaUserLevels) || typeof settings.previewMediaUserLevels === "string") {
1879
+ const selected = new Set(normalizeMediaPreviewUserLevels(settings.previewMediaUserLevels));
1880
+ return {
1881
+ previewMediaForViewers: selected.has("regular") || selected.has("follower") || selected.has("anyone"),
1882
+ previewMediaForSubscribers: selected.has("subscribers"),
1883
+ previewMediaForVips: selected.has("vips"),
1884
+ previewMediaForModerators: selected.has("moderators"),
1885
+ previewMediaForStreamer: selected.has("streamer"),
1886
+ previewMediaForTier3: selected.has("tier3"),
1887
+ previewMediaForTier2: selected.has("tier2"),
1888
+ previewMediaForRegular: selected.has("regular"),
1889
+ previewMediaForFollower: selected.has("follower"),
1890
+ previewMediaForAnyone: selected.has("anyone")
1891
+ };
1892
+ }
1893
+ const previewMediaForViewers = resolveMediaPreviewSetting(settings.previewMediaForViewers, true);
1894
+ const previewMediaForSubscribers = resolveMediaPreviewSetting(settings.previewMediaForSubscribers, true);
1895
+ return {
1896
+ previewMediaForViewers,
1897
+ previewMediaForSubscribers,
1898
+ previewMediaForVips: resolveMediaPreviewSetting(settings.previewMediaForVips, true),
1899
+ previewMediaForModerators: resolveMediaPreviewSetting(settings.previewMediaForModerators, true),
1900
+ previewMediaForStreamer: resolveMediaPreviewSetting(settings.previewMediaForStreamer, true),
1901
+ previewMediaForTier3: resolveMediaPreviewSetting(settings.previewMediaForTier3, previewMediaForSubscribers),
1902
+ previewMediaForTier2: resolveMediaPreviewSetting(settings.previewMediaForTier2, previewMediaForSubscribers),
1903
+ previewMediaForRegular: resolveMediaPreviewSetting(settings.previewMediaForRegular, previewMediaForViewers),
1904
+ previewMediaForFollower: resolveMediaPreviewSetting(settings.previewMediaForFollower, previewMediaForViewers),
1905
+ previewMediaForAnyone: resolveMediaPreviewSetting(settings.previewMediaForAnyone, previewMediaForViewers)
1906
+ };
1907
+ };
1908
+ var getNormalizedUserLevels = (value) => {
1909
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1910
+ return {};
1911
+ }
1912
+ const normalized = {};
1913
+ for (const [key, levelValue] of Object.entries(value)) {
1914
+ normalized[key.toLowerCase()] = Boolean(levelValue);
1915
+ }
1916
+ return normalized;
1917
+ };
1918
+ var isMediaPreviewAllowedForUser = (userLevelsRaw, roleSettings) => {
1919
+ const levels = getNormalizedUserLevels(userLevelsRaw);
1920
+ const isStreamer = levels.isself || levels.self || levels.streamer || levels.broadcaster || levels.owner;
1921
+ const isModerator = levels.mod || levels.moderator;
1922
+ const isVip = levels.vip || levels.vips;
1923
+ const isTier3 = levels.tier3 || levels.tier_3;
1924
+ const isTier2 = levels.tier2 || levels.tier_2;
1925
+ const isSubscriber = levels.subscriber || levels.sub || levels.member || levels.members || levels.tier1 || levels.tier_1;
1926
+ const isRegular = levels.regular;
1927
+ const isFollower = levels.follower || levels.followers;
1928
+ return isStreamer && roleSettings.previewMediaForStreamer || isModerator && roleSettings.previewMediaForModerators || isVip && roleSettings.previewMediaForVips || isTier3 && roleSettings.previewMediaForTier3 || isTier2 && roleSettings.previewMediaForTier2 || isSubscriber && roleSettings.previewMediaForSubscribers || isRegular && roleSettings.previewMediaForRegular || isFollower && roleSettings.previewMediaForFollower || roleSettings.previewMediaForAnyone;
1929
+ };
1930
+ var parseExternalUrl = (url) => {
1931
+ try {
1932
+ return new URL(url);
1933
+ } catch {
1934
+ return null;
1935
+ }
1936
+ };
1937
+ var decodeURIComponentSafe = (value) => {
1938
+ try {
1939
+ return decodeURIComponent(value);
1940
+ } catch {
1941
+ return value;
1942
+ }
1943
+ };
1944
+ var sanitizeMediaTitle = (value) => {
1945
+ return decodeURIComponentSafe(value.replace(/\+/g, " ")).replace(/\.[^./?#]+$/, "").replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
1946
+ };
1947
+ var tryExtractFilename = (value) => {
1948
+ const trimmed = value.trim();
1949
+ if (!trimmed) {
1950
+ return "";
1951
+ }
1952
+ const normalizedUrl = /^https?:\/\//i.test(trimmed) ? trimmed : trimmed.startsWith("www.") ? `https://${trimmed}` : "";
1953
+ if (normalizedUrl) {
1954
+ const parsed = parseExternalUrl(normalizedUrl);
1955
+ if (parsed) {
1956
+ const segment2 = parsed.pathname.split("/").filter(Boolean).pop() ?? "";
1957
+ const decoded = decodeURIComponentSafe(segment2).trim();
1958
+ if (decoded) {
1959
+ return decoded;
1960
+ }
1961
+ }
1962
+ }
1963
+ const withoutQueryAndHash = trimmed.split(/[?#]/)[0] ?? "";
1964
+ const segment = withoutQueryAndHash.split("/").filter(Boolean).pop() ?? "";
1965
+ return decodeURIComponentSafe(segment).trim();
1966
+ };
1967
+ var getAudioTitleFromUrl = (url) => {
1968
+ const parsed = parseExternalUrl(url);
1969
+ if (!parsed) {
1970
+ return "Audio";
1971
+ }
1972
+ for (const queryKey of ["title", "name", "filename", "file"]) {
1973
+ const rawValue = parsed.searchParams.get(queryKey);
1974
+ const filename = rawValue ? tryExtractFilename(rawValue) : "";
1975
+ if (filename) {
1976
+ return filename;
1977
+ }
1978
+ }
1979
+ const pathFilename = tryExtractFilename(parsed.pathname);
1980
+ if (pathFilename) {
1981
+ return pathFilename;
1982
+ }
1983
+ for (const queryKey of ["title", "name", "filename", "file"]) {
1984
+ const rawValue = parsed.searchParams.get(queryKey);
1985
+ const normalized = rawValue ? sanitizeMediaTitle(rawValue) : "";
1986
+ if (normalized) {
1987
+ return normalized;
1988
+ }
1989
+ }
1990
+ const pathSegment = parsed.pathname.split("/").filter(Boolean).pop() ?? "";
1991
+ const normalizedPathTitle = sanitizeMediaTitle(pathSegment);
1992
+ return normalizedPathTitle || "Audio";
1993
+ };
1994
+ var extractYoutubeEmbedInfo = (url) => {
1995
+ const parsed = parseExternalUrl(url);
1996
+ if (!parsed) {
1997
+ return null;
1998
+ }
1999
+ const hostname = parsed.hostname.replace(/^www\./i, "").toLowerCase();
2000
+ let videoId = "";
2001
+ let isShort = false;
2002
+ if (hostname === "youtu.be") {
2003
+ videoId = parsed.pathname.split("/").filter(Boolean)[0] ?? "";
2004
+ } else if (hostname.endsWith("youtube.com") || hostname === "youtube-nocookie.com") {
2005
+ const segments = parsed.pathname.split("/").filter(Boolean);
2006
+ if (segments[0] === "watch") {
2007
+ videoId = parsed.searchParams.get("v") ?? "";
2008
+ } else if (segments[0] === "shorts") {
2009
+ videoId = segments[1] ?? "";
2010
+ isShort = true;
2011
+ } else if (["embed", "live", "v"].includes(segments[0] ?? "")) {
2012
+ videoId = segments[1] ?? "";
2013
+ }
2014
+ }
2015
+ const cleaned = videoId.trim();
2016
+ return YOUTUBE_ID_REGEX.test(cleaned) ? { id: cleaned, isShort } : null;
2017
+ };
2018
+ var extractSpotifyEmbedUrl = (url) => {
2019
+ const parsed = parseExternalUrl(url);
2020
+ if (!parsed) {
2021
+ return null;
2022
+ }
2023
+ const hostname = parsed.hostname.replace(/^www\./i, "").toLowerCase();
2024
+ if (hostname !== "open.spotify.com" && hostname !== "play.spotify.com") {
2025
+ return null;
2026
+ }
2027
+ const segments = parsed.pathname.split("/").filter(Boolean);
2028
+ let type = segments[0] ?? "";
2029
+ let id = segments[1] ?? "";
2030
+ if (type === "intl" && segments.length >= 4) {
2031
+ type = segments[2] ?? "";
2032
+ id = segments[3] ?? "";
2033
+ }
2034
+ if (!SPOTIFY_EMBED_TYPES.has(type) || !id) {
2035
+ return null;
2036
+ }
2037
+ return `https://open.spotify.com/embed/${type}/${id}`;
2038
+ };
2039
+ var getMediaPreviewFromUrl = (url) => {
2040
+ if (MEDIA_IMAGE_REGEX.test(url)) {
2041
+ return { kind: "image", src: url };
2042
+ }
2043
+ if (MEDIA_AUDIO_REGEX.test(url)) {
2044
+ return { kind: "audio", src: url, title: getAudioTitleFromUrl(url) };
2045
+ }
2046
+ if (MEDIA_VIDEO_REGEX.test(url)) {
2047
+ return { kind: "video", src: url };
2048
+ }
2049
+ const youtube = extractYoutubeEmbedInfo(url);
2050
+ if (youtube) {
2051
+ return { kind: youtube.isShort ? "youtubeShort" : "youtube", src: `https://www.youtube.com/embed/${youtube.id}` };
2052
+ }
2053
+ const spotifyEmbed = extractSpotifyEmbedUrl(url);
2054
+ if (spotifyEmbed) {
2055
+ return { kind: "spotify", src: spotifyEmbed };
2056
+ }
2057
+ return null;
2058
+ };
2059
+ var normalizeProfilePlatform = (value) => {
2060
+ if (value === null || value === void 0) {
2061
+ return "";
2062
+ }
2063
+ return String(value).trim().toLowerCase();
2064
+ };
2065
+ var normalizeProfileHandle = (value) => {
2066
+ const text = typeof value === "string" || typeof value === "number" ? String(value).trim() : "";
2067
+ return text.replace(/^@+/, "");
2068
+ };
2069
+ var resolvePlatformChatterProfileUrl = ({ platform, username, displayname, userId }) => {
2070
+ const normalizedPlatform = normalizeProfilePlatform(platform);
2071
+ if (!normalizedPlatform) {
2072
+ return null;
2073
+ }
2074
+ const normalizedUsername = normalizeProfileHandle(username) || normalizeProfileHandle(displayname);
2075
+ const normalizedUserId = typeof userId === "string" || typeof userId === "number" ? String(userId).trim() : "";
2076
+ switch (normalizedPlatform) {
2077
+ case "twitch":
2078
+ return normalizedUsername ? `https://www.twitch.tv/${encodeURIComponent(normalizedUsername)}` : null;
2079
+ case "youtube":
2080
+ case "youtubegaming":
2081
+ if (/^UC[\w-]+$/i.test(normalizedUserId)) {
2082
+ return `https://www.youtube.com/channel/${encodeURIComponent(normalizedUserId)}`;
2083
+ }
2084
+ if (normalizedUsername) {
2085
+ return `https://www.youtube.com/@${encodeURIComponent(normalizedUsername)}`;
2086
+ }
2087
+ return normalizedUserId ? `https://www.youtube.com/channel/${encodeURIComponent(normalizedUserId)}` : null;
2088
+ case "facebook":
2089
+ if (normalizedUserId) {
2090
+ return `https://www.facebook.com/${encodeURIComponent(normalizedUserId)}`;
2091
+ }
2092
+ return normalizedUsername ? `https://www.facebook.com/${encodeURIComponent(normalizedUsername)}` : null;
2093
+ case "tiktok":
2094
+ return normalizedUsername ? `https://www.tiktok.com/@${encodeURIComponent(normalizedUsername)}` : null;
2095
+ case "kick":
2096
+ return normalizedUsername ? `https://kick.com/${encodeURIComponent(normalizedUsername)}` : null;
2097
+ case "discord":
2098
+ return normalizedUserId ? `https://discord.com/users/${encodeURIComponent(normalizedUserId)}` : null;
2099
+ case "trovo":
2100
+ return normalizedUsername ? `https://trovo.live/${encodeURIComponent(normalizedUsername)}` : null;
2101
+ default:
2102
+ return null;
2103
+ }
2104
+ };
2105
+ var normalizeHttpUrl = (value) => {
2106
+ const candidate = typeof value === "string" ? value.trim() : "";
2107
+ if (!candidate) {
2108
+ return null;
2109
+ }
2110
+ const normalized = candidate.startsWith("http://") || candidate.startsWith("https://") ? candidate : candidate.startsWith("www.") ? `https://${candidate}` : candidate;
2111
+ const parsed = parseExternalUrl(normalized);
2112
+ if (!parsed || !/^https?:$/i.test(parsed.protocol)) {
2113
+ return null;
2114
+ }
2115
+ return normalized;
2116
+ };
2117
+ var resolveChatterProfileUrlWithResolvers = async ({
2118
+ platform,
2119
+ username,
2120
+ displayname,
2121
+ userId,
2122
+ extraSettings,
2123
+ resolvers
2124
+ }) => {
2125
+ const normalizedPlatform = normalizeProfilePlatform(platform);
2126
+ const normalizedUsername = normalizeProfileHandle(username);
2127
+ const normalizedDisplayName = normalizeProfileHandle(displayname);
2128
+ const normalizedUserId = typeof userId === "string" || typeof userId === "number" ? String(userId).trim() : "";
2129
+ const payload = {
2130
+ username: normalizedUsername || void 0,
2131
+ displayname: normalizedDisplayName || void 0,
2132
+ userId: normalizedUserId || void 0,
2133
+ platform: normalizedPlatform || void 0,
2134
+ extraSettings
2135
+ };
2136
+ for (const resolver of resolvers ?? []) {
2137
+ if (typeof resolver !== "function") {
2138
+ continue;
2139
+ }
2140
+ try {
2141
+ const resolved = await resolver(payload);
2142
+ const normalizedResolvedUrl = normalizeHttpUrl(resolved);
2143
+ if (normalizedResolvedUrl) {
2144
+ return normalizedResolvedUrl;
2145
+ }
2146
+ } catch {
2147
+ }
2148
+ }
2149
+ return resolvePlatformChatterProfileUrl({
2150
+ platform: normalizedPlatform || platform,
2151
+ username: normalizedUsername || normalizedDisplayName,
2152
+ userId: normalizedUserId || void 0
2153
+ });
2154
+ };
268
2155
  export {
269
2156
  LSButton,
2157
+ LSCheckbox,
2158
+ LSCheckboxField,
2159
+ LSColorPicker,
2160
+ LSFontPicker,
2161
+ LSInput,
2162
+ LSMultiSelect,
2163
+ LSRadio,
2164
+ LSRadioGroup,
2165
+ LSSelect,
2166
+ LSSliderInput,
2167
+ LSTextField,
2168
+ LSVariableInputField,
2169
+ LSVariableInputProvider,
2170
+ MEDIA_PREVIEW_USER_LEVEL_VALUES,
2171
+ buildChatMessageContent,
270
2172
  codeMirrorlinterOptions,
2173
+ getMediaPreviewFromUrl,
2174
+ getNormalizedUserLevels,
2175
+ isMediaPreviewAllowedForUser,
2176
+ normalizeHttpUrl,
2177
+ normalizeMediaPreviewUserLevels,
2178
+ parseMessageLinks,
2179
+ resolveChatterProfileUrlWithResolvers,
2180
+ resolveMediaPreviewRoleSettings,
2181
+ resolveMediaPreviewSetting,
2182
+ resolvePlatformChatterProfileUrl,
2183
+ tokenizeChatMessage,
271
2184
  variableCompletionOptions
272
2185
  };