@steez-ui/ui 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/components/AvatarStage.js.map +1 -1
- package/dist/components/BlinkText.js.map +1 -1
- package/dist/components/Button.js.map +1 -1
- package/dist/components/CopyButton.js.map +1 -1
- package/dist/components/CornerBracketCard.js.map +1 -1
- package/dist/components/CyberpunkCheckbox.js.map +1 -1
- package/dist/components/CyberpunkInput.js.map +1 -1
- package/dist/components/CyberpunkRadio.js.map +1 -1
- package/dist/components/CyberpunkSelect.js.map +1 -1
- package/dist/components/CyberpunkSlider.js.map +1 -1
- package/dist/components/CyberpunkTextarea.js.map +1 -1
- package/dist/components/CyberpunkTile.js.map +1 -1
- package/dist/components/ErrorMessage.js.map +1 -1
- package/dist/components/HeartbeatPulse.js.map +1 -1
- package/dist/components/HexagonGrid.d.ts +12 -0
- package/dist/components/HexagonGrid.d.ts.map +1 -0
- package/dist/components/HexagonGrid.js +284 -0
- package/dist/components/HexagonGrid.js.map +1 -0
- package/dist/components/HexagonGrid.module.css +14 -0
- package/dist/components/LoadingProgressBar.js.map +1 -1
- package/dist/components/MarqueeStrip.js.map +1 -1
- package/dist/components/PageHeader.js.map +1 -1
- package/dist/components/PageTemplate.js.map +1 -1
- package/dist/components/QuickInfoCard.d.ts +20 -0
- package/dist/components/QuickInfoCard.d.ts.map +1 -0
- package/dist/components/QuickInfoCard.js +38 -0
- package/dist/components/QuickInfoCard.js.map +1 -0
- package/dist/components/QuickInfoCard.module.css +138 -0
- package/dist/components/RuntimeOrbitDiagram.d.ts +19 -0
- package/dist/components/RuntimeOrbitDiagram.d.ts.map +1 -0
- package/dist/components/RuntimeOrbitDiagram.js +39 -0
- package/dist/components/RuntimeOrbitDiagram.js.map +1 -0
- package/dist/components/RuntimeOrbitDiagram.module.css +160 -0
- package/dist/components/Section.d.ts +9 -0
- package/dist/components/Section.d.ts.map +1 -0
- package/dist/components/Section.js +7 -0
- package/dist/components/Section.js.map +1 -0
- package/dist/components/Section.module.css +20 -0
- package/dist/components/SectionHeader.d.ts +10 -0
- package/dist/components/SectionHeader.d.ts.map +1 -0
- package/dist/components/SectionHeader.js +7 -0
- package/dist/components/SectionHeader.js.map +1 -0
- package/dist/components/SectionHeader.module.css +54 -0
- package/dist/components/SegmentedControl.js.map +1 -1
- package/dist/components/StatCard.d.ts +11 -0
- package/dist/components/StatCard.d.ts.map +1 -0
- package/dist/components/StatCard.js +14 -0
- package/dist/components/StatCard.js.map +1 -0
- package/dist/components/StatCard.module.css +41 -0
- package/dist/components/StatusMessage.js.map +1 -1
- package/dist/components/StrokedText.js.map +1 -1
- package/dist/components/TabbedPanel.js.map +1 -1
- package/dist/components/ThemeToggle.js.map +1 -1
- package/dist/components/ThemedCard.js.map +1 -1
- package/dist/hooks/useStableId.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarqueeStrip.js","sourceRoot":"","sources":["../../src/components/MarqueeStrip.tsx"],"names":[],"mappings":";AAEA,OAAO,MAAM,MAAM,2BAA2B,CAAC;AAa/C,MAAM,UAAU,YAAY,CAAI,EAC9B,KAAK,EACL,UAAU,EACV,SAAS,EACT,eAAe,GAAG,EAAE,EACpB,GAAG,GAAG,QAAQ,EACd,YAAY,GAAG,KAAK,EACpB,SAAS,GAAG,EAAE,EACd,cAAc,GAAG,EAAE,EACnB,aAAa,GAAG,EAAE,EAClB,KAAK,EACL,GAAG,KAAK,EACa;IACrB,MAAM,YAAY,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG;QAClB,GAAG,KAAK;QACR,CAAC,oBAA8B,CAAC,EAAE,GAAG,eAAe,GAAG;QACvD,CAAC,eAAyB,CAAC,EACzB,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG;KACtB,CAAC;IAEzB,OAAO,CACL,cACE,SAAS,EAAE,GAAG,MAAM,CAAC,IAAI,IAAI,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,SAAS,EAAE,CAAC,IAAI,EAAE,gBAC9E,SAAS,EACrB,KAAK,EAAE,WAAW,KACd,KAAK,YAET,cAAK,SAAS,EAAE,GAAG,MAAM,CAAC,KAAK,IAAI,cAAc,EAAE,CAAC,IAAI,EAAE,YACvD,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CACjC,cAEE,SAAS,EAAE,GAAG,MAAM,CAAC,IAAI,IAAI,aAAa,EAAE,CAAC,IAAI,EAAE,iBACtC,KAAK,IAAI,KAAK,CAAC,MAAM,YAEjC,UAAU,CAAC,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,IAJlC,KAAK,CAKN,CACP,CAAC,GACE,GACF,CACP,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"MarqueeStrip.js","sourceRoot":"","sources":["../../src/components/MarqueeStrip.tsx"],"names":[],"mappings":";AAEA,OAAO,MAAM,MAAM,2BAA2B,CAAC;AAa/C,MAAM,UAAU,YAAY,CAAI,EAC9B,KAAK,EACL,UAAU,EACV,SAAS,EACT,eAAe,GAAG,EAAE,EACpB,GAAG,GAAG,QAAQ,EACd,YAAY,GAAG,KAAK,EACpB,SAAS,GAAG,EAAE,EACd,cAAc,GAAG,EAAE,EACnB,aAAa,GAAG,EAAE,EAClB,KAAK,EACL,GAAG,KAAK,EACa;IACrB,MAAM,YAAY,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG;QAClB,GAAG,KAAK;QACR,CAAC,oBAA8B,CAAC,EAAE,GAAG,eAAe,GAAG;QACvD,CAAC,eAAyB,CAAC,EACzB,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG;KACtB,CAAC;IAEzB,OAAO,CACL,cACE,SAAS,EAAE,GAAG,MAAM,CAAC,IAAI,IAAI,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,SAAS,EAAE,CAAC,IAAI,EAAE,gBAC9E,SAAS,EACrB,KAAK,EAAE,WAAW,KACd,KAAK,YAET,cAAK,SAAS,EAAE,GAAG,MAAM,CAAC,KAAK,IAAI,cAAc,EAAE,CAAC,IAAI,EAAE,YACvD,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CACjC,cAEE,SAAS,EAAE,GAAG,MAAM,CAAC,IAAI,IAAI,aAAa,EAAE,CAAC,IAAI,EAAE,iBACtC,KAAK,IAAI,KAAK,CAAC,MAAM,YAEjC,UAAU,CAAC,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,IAJlC,KAAK,CAKN,CACP,CAAC,GACE,GACF,CACP,CAAC;AACJ,CAAC","sourcesContent":["import React from \"react\";\n\nimport styles from \"./MarqueeStrip.module.css\";\n\nexport interface MarqueeStripProps<T> extends React.HTMLAttributes<HTMLDivElement> {\n items: readonly T[];\n renderItem: (item: T, index: number) => React.ReactNode;\n ariaLabel?: string;\n durationSeconds?: number;\n gap?: number | string;\n pauseOnHover?: boolean;\n trackClassName?: string;\n itemClassName?: string;\n}\n\nexport function MarqueeStrip<T>({\n items,\n renderItem,\n ariaLabel,\n durationSeconds = 24,\n gap = \"0.7rem\",\n pauseOnHover = false,\n className = \"\",\n trackClassName = \"\",\n itemClassName = \"\",\n style,\n ...props\n}: MarqueeStripProps<T>) {\n const doubledItems = [...items, ...items];\n const mergedStyle = {\n ...style,\n [\"--marquee-duration\" as string]: `${durationSeconds}s`,\n [\"--marquee-gap\" as string]:\n typeof gap === \"number\" ? `${gap}px` : gap,\n } as React.CSSProperties;\n\n return (\n <div\n className={`${styles.root} ${pauseOnHover ? styles.pauseOnHover : \"\"} ${className}`.trim()}\n aria-label={ariaLabel}\n style={mergedStyle}\n {...props}\n >\n <div className={`${styles.track} ${trackClassName}`.trim()}>\n {doubledItems.map((item, index) => (\n <div\n key={index}\n className={`${styles.item} ${itemClassName}`.trim()}\n aria-hidden={index >= items.length}\n >\n {renderItem(item, index % items.length)}\n </div>\n ))}\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageHeader.js","sourceRoot":"","sources":["../../src/components/PageHeader.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG7D,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAoB7C,MAAM,UAAU,UAAU,CAAC,EACzB,KAAK,EACL,WAAW,EACX,IAAI,EACJ,KAAK,EACL,SAAS,GAAG,EAAE,EACd,KAAK,EACL,YAAY,EACZ,UAAU,EACV,cAAc,EACd,MAAM,EACN,UAAU,EACV,cAAc,EACd,aAAa,EACb,eAAe,GAAG,aAAa,EAC/B,eAAe,GAAG,aAAa,GACf;IAChB,MAAM,WAAW,GAAG,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC;IAEtE,OAAO,CACL,cAAK,SAAS,EAAE,GAAG,MAAM,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC,IAAI,EAAE,YACpD,eAAK,SAAS,EAAE,MAAM,CAAC,SAAS,aAC9B,eAAK,SAAS,EAAE,MAAM,CAAC,YAAY,aAChC,KAAK,IAAI,YAAY,CAAC,CAAC,CAAC,CACvB,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,MAAM,CAAC,WAAW,EAC7B,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE,UAAU,gBACL,cAAc,YAE1B,eAAM,SAAS,EAAE,MAAM,CAAC,WAAW,YAAG,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAQ,GACjE,CACV,CAAC,CAAC,CAAC,IAAI,EACR,eAAK,SAAS,EAAE,MAAM,CAAC,aAAa,aAClC,yBACG,IAAI,CAAC,CAAC,CAAC,CACN,eAAM,SAAS,EAAE,MAAM,CAAC,SAAS,YAC/B,KAAC,IAAI,IAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,GAAI,GACtC,CACR,CAAC,CAAC,CAAC,IAAI,EACP,KAAK,IACH,EACJ,WAAW,CAAC,CAAC,CAAC,sBAAI,WAAW,GAAK,CAAC,CAAC,CAAC,IAAI,IACtC,IACF,EACN,eAAK,SAAS,EAAE,MAAM,CAAC,WAAW,aAC/B,KAAK,EACL,MAAM,CAAC,CAAC,CAAC,CACR,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,gBAAa,SAAS,YACvF,KAAC,IAAI,IAAC,IAAI,EAAC,aAAa,EAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,GAAI,GAC3C,CACV,CAAC,CAAC,CAAC,IAAI,EACP,UAAU,CAAC,CAAC,CAAC,CACZ,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,UAAU,gBAAa,eAAe,YACjG,KAAC,WAAW,IAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,GAAI,GAC/B,CACV,CAAC,CAAC,CAAC,IAAI,EACP,cAAc,CAAC,CAAC,CAAC,CAChB,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,MAAM,CAAC,UAAU,EAC5B,OAAO,EAAE,cAAc,gBACX,WAAW,EACvB,KAAK,EAAE,WAAW,YAElB,KAAC,OAAO,IAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,GAAI,GAC3B,CACV,CAAC,CAAC,CAAC,IAAI,IACJ,IACF,GACF,CACP,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"PageHeader.js","sourceRoot":"","sources":["../../src/components/PageHeader.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG7D,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAoB7C,MAAM,UAAU,UAAU,CAAC,EACzB,KAAK,EACL,WAAW,EACX,IAAI,EACJ,KAAK,EACL,SAAS,GAAG,EAAE,EACd,KAAK,EACL,YAAY,EACZ,UAAU,EACV,cAAc,EACd,MAAM,EACN,UAAU,EACV,cAAc,EACd,aAAa,EACb,eAAe,GAAG,aAAa,EAC/B,eAAe,GAAG,aAAa,GACf;IAChB,MAAM,WAAW,GAAG,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC;IAEtE,OAAO,CACL,cAAK,SAAS,EAAE,GAAG,MAAM,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC,IAAI,EAAE,YACpD,eAAK,SAAS,EAAE,MAAM,CAAC,SAAS,aAC9B,eAAK,SAAS,EAAE,MAAM,CAAC,YAAY,aAChC,KAAK,IAAI,YAAY,CAAC,CAAC,CAAC,CACvB,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,MAAM,CAAC,WAAW,EAC7B,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE,UAAU,gBACL,cAAc,YAE1B,eAAM,SAAS,EAAE,MAAM,CAAC,WAAW,YAAG,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAQ,GACjE,CACV,CAAC,CAAC,CAAC,IAAI,EACR,eAAK,SAAS,EAAE,MAAM,CAAC,aAAa,aAClC,yBACG,IAAI,CAAC,CAAC,CAAC,CACN,eAAM,SAAS,EAAE,MAAM,CAAC,SAAS,YAC/B,KAAC,IAAI,IAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,GAAI,GACtC,CACR,CAAC,CAAC,CAAC,IAAI,EACP,KAAK,IACH,EACJ,WAAW,CAAC,CAAC,CAAC,sBAAI,WAAW,GAAK,CAAC,CAAC,CAAC,IAAI,IACtC,IACF,EACN,eAAK,SAAS,EAAE,MAAM,CAAC,WAAW,aAC/B,KAAK,EACL,MAAM,CAAC,CAAC,CAAC,CACR,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,gBAAa,SAAS,YACvF,KAAC,IAAI,IAAC,IAAI,EAAC,aAAa,EAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,GAAI,GAC3C,CACV,CAAC,CAAC,CAAC,IAAI,EACP,UAAU,CAAC,CAAC,CAAC,CACZ,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,UAAU,gBAAa,eAAe,YACjG,KAAC,WAAW,IAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,GAAI,GAC/B,CACV,CAAC,CAAC,CAAC,IAAI,EACP,cAAc,CAAC,CAAC,CAAC,CAChB,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,MAAM,CAAC,UAAU,EAC5B,OAAO,EAAE,cAAc,gBACX,WAAW,EACvB,KAAK,EAAE,WAAW,YAElB,KAAC,OAAO,IAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,GAAI,GAC3B,CACV,CAAC,CAAC,CAAC,IAAI,IACJ,IACF,GACF,CACP,CAAC;AACJ,CAAC","sourcesContent":["import React, { ReactNode } from \"react\";\n\nimport { EyeIcon, Icon, SlidersIcon } from \"@steez-ui/icons\";\nimport type { SteezIconName } from \"@steez-ui/icons\";\n\nimport styles from \"./PageHeader.module.css\";\n\nexport interface PageHeaderProps {\n title: string;\n description?: string;\n icon?: SteezIconName;\n extra?: ReactNode;\n className?: string;\n brand?: ReactNode;\n onBrandClick?: () => void;\n brandTitle?: string;\n brandAriaLabel?: string;\n onBack?: () => void;\n onSettings?: () => void;\n onViewerToggle?: () => void;\n viewerVisible?: boolean;\n viewerShowLabel?: string;\n viewerHideLabel?: string;\n}\n\nexport function PageHeader({\n title,\n description,\n icon,\n extra,\n className = \"\",\n brand,\n onBrandClick,\n brandTitle,\n brandAriaLabel,\n onBack,\n onSettings,\n onViewerToggle,\n viewerVisible,\n viewerShowLabel = \"Show viewer\",\n viewerHideLabel = \"Hide viewer\",\n}: PageHeaderProps) {\n const viewerLabel = viewerVisible ? viewerHideLabel : viewerShowLabel;\n\n return (\n <div className={`${styles.header} ${className}`.trim()}>\n <div className={styles.headerRow}>\n <div className={styles.brandCluster}>\n {brand || onBrandClick ? (\n <button\n type=\"button\"\n className={styles.brandButton}\n onClick={onBrandClick}\n title={brandTitle}\n aria-label={brandAriaLabel}\n >\n <span className={styles.brandVisual}>{brand ?? title.slice(0, 1)}</span>\n </button>\n ) : null}\n <div className={styles.headerContent}>\n <h2>\n {icon ? (\n <span className={styles.titleIcon}>\n <Icon icon={icon} width={18} height={18} />\n </span>\n ) : null}\n {title}\n </h2>\n {description ? <p>{description}</p> : null}\n </div>\n </div>\n <div className={styles.headerExtra}>\n {extra}\n {onBack ? (\n <button type=\"button\" className={styles.iconButton} onClick={onBack} aria-label=\"Go back\">\n <Icon icon=\"chevronLeft\" width={18} height={18} />\n </button>\n ) : null}\n {onSettings ? (\n <button type=\"button\" className={styles.iconButton} onClick={onSettings} aria-label=\"Open settings\">\n <SlidersIcon width={18} height={18} />\n </button>\n ) : null}\n {onViewerToggle ? (\n <button\n type=\"button\"\n className={styles.iconButton}\n onClick={onViewerToggle}\n aria-label={viewerLabel}\n title={viewerLabel}\n >\n <EyeIcon width={18} height={18} />\n </button>\n ) : null}\n </div>\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageTemplate.js","sourceRoot":"","sources":["../../src/components/PageTemplate.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,UAAU,EAAwB,MAAM,iBAAiB,CAAC;AACnE,OAAO,MAAM,MAAM,2BAA2B,CAAC;AAmC/C,MAAM,UAAU,YAAY,CAAC,EAC3B,KAAK,EACL,OAAO,EACP,KAAK,EACL,WAAW,EACX,IAAI,EACJ,OAAO,EACP,YAAY,EACZ,cAAc,EACd,MAAM,EACN,UAAU,EACV,KAAK,EACL,YAAY,EACZ,cAAc,EACd,aAAa,EACb,UAAU,EACV,cAAc,EACd,eAAe,EACf,eAAe,EACf,QAAQ,EACR,OAAO,EACP,SAAS,GAAG,IAAI,EAChB,SAAS,GAAG,EAAE,GACI;IAClB,MAAM,WAAW,GAAG,KAAK,IAAI,OAAO,CAAC;IAErC,OAAO,CACL,eAAK,SAAS,EAAE,GAAG,MAAM,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC,IAAI,EAAE,aACjD,SAAS,CAAC,CAAC,CAAC,CACX,cAAK,SAAS,EAAE,MAAM,CAAC,MAAM,YAC3B,KAAC,UAAU,IACT,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,YAAY,EAC1B,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,cAAc,EAC9B,cAAc,EAAE,cAAc,EAC9B,aAAa,EAAE,aAAa,EAC5B,eAAe,EAAE,eAAe,EAChC,eAAe,EAAE,eAAe,GAChC,GACE,CACP,CAAC,CAAC,CAAC,IAAI,EAEP,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CACjB,cAAK,SAAS,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAC,SAAS,gBAAa,GAAG,KAAK,WAAW,YAC3E,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACpB,iBAEE,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EACvC,SAAS,EAAE,GAAG,MAAM,CAAC,YAAY,IAAI,YAAY,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,EACtG,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,KAAK,mBACK,YAAY,KAAK,GAAG,CAAC,EAAE,YAErC,GAAG,CAAC,KAAK,IAPL,GAAG,CAAC,EAAE,CAQJ,CACV,CAAC,GACE,CACP,CAAC,CAAC,CAAC,IAAI,EAER,cAAK,SAAS,EAAE,MAAM,CAAC,OAAO,YAC3B,OAAO,CAAC,CAAC,CAAC,cAAK,SAAS,EAAE,MAAM,CAAC,OAAO,2BAAkB,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAI,GAC1E,IACF,CACP,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"PageTemplate.js","sourceRoot":"","sources":["../../src/components/PageTemplate.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,UAAU,EAAwB,MAAM,iBAAiB,CAAC;AACnE,OAAO,MAAM,MAAM,2BAA2B,CAAC;AAmC/C,MAAM,UAAU,YAAY,CAAC,EAC3B,KAAK,EACL,OAAO,EACP,KAAK,EACL,WAAW,EACX,IAAI,EACJ,OAAO,EACP,YAAY,EACZ,cAAc,EACd,MAAM,EACN,UAAU,EACV,KAAK,EACL,YAAY,EACZ,cAAc,EACd,aAAa,EACb,UAAU,EACV,cAAc,EACd,eAAe,EACf,eAAe,EACf,QAAQ,EACR,OAAO,EACP,SAAS,GAAG,IAAI,EAChB,SAAS,GAAG,EAAE,GACI;IAClB,MAAM,WAAW,GAAG,KAAK,IAAI,OAAO,CAAC;IAErC,OAAO,CACL,eAAK,SAAS,EAAE,GAAG,MAAM,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC,IAAI,EAAE,aACjD,SAAS,CAAC,CAAC,CAAC,CACX,cAAK,SAAS,EAAE,MAAM,CAAC,MAAM,YAC3B,KAAC,UAAU,IACT,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,YAAY,EAC1B,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,cAAc,EAC9B,cAAc,EAAE,cAAc,EAC9B,aAAa,EAAE,aAAa,EAC5B,eAAe,EAAE,eAAe,EAChC,eAAe,EAAE,eAAe,GAChC,GACE,CACP,CAAC,CAAC,CAAC,IAAI,EAEP,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CACjB,cAAK,SAAS,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAC,SAAS,gBAAa,GAAG,KAAK,WAAW,YAC3E,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACpB,iBAEE,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EACvC,SAAS,EAAE,GAAG,MAAM,CAAC,YAAY,IAAI,YAAY,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,EACtG,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,KAAK,mBACK,YAAY,KAAK,GAAG,CAAC,EAAE,YAErC,GAAG,CAAC,KAAK,IAPL,GAAG,CAAC,EAAE,CAQJ,CACV,CAAC,GACE,CACP,CAAC,CAAC,CAAC,IAAI,EAER,cAAK,SAAS,EAAE,MAAM,CAAC,OAAO,YAC3B,OAAO,CAAC,CAAC,CAAC,cAAK,SAAS,EAAE,MAAM,CAAC,OAAO,2BAAkB,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAI,GAC1E,IACF,CACP,CAAC;AACJ,CAAC","sourcesContent":["import React from \"react\";\n\nimport { PageHeader, type PageHeaderProps } from \"./PageHeader.js\";\nimport styles from \"./PageTemplate.module.css\";\n\ninterface SubTab {\n id: string;\n label: string;\n}\n\nexport interface PageTemplateProps\n extends Pick<\n PageHeaderProps,\n | \"title\"\n | \"description\"\n | \"icon\"\n | \"onBack\"\n | \"onSettings\"\n | \"brand\"\n | \"onBrandClick\"\n | \"onViewerToggle\"\n | \"viewerVisible\"\n > {\n actions?: React.ReactNode;\n extra?: React.ReactNode;\n className?: string;\n subTabs?: SubTab[];\n activeSubTab?: string;\n onSubTabChange?: (tabId: string) => void;\n children?: React.ReactNode;\n loading?: boolean;\n showTitle?: boolean;\n brandTitle?: string;\n brandAriaLabel?: string;\n viewerShowLabel?: string;\n viewerHideLabel?: string;\n}\n\nexport function PageTemplate({\n title,\n actions,\n extra,\n description,\n icon,\n subTabs,\n activeSubTab,\n onSubTabChange,\n onBack,\n onSettings,\n brand,\n onBrandClick,\n onViewerToggle,\n viewerVisible,\n brandTitle,\n brandAriaLabel,\n viewerShowLabel,\n viewerHideLabel,\n children,\n loading,\n showTitle = true,\n className = \"\",\n}: PageTemplateProps) {\n const headerExtra = extra ?? actions;\n\n return (\n <div className={`${styles.root} ${className}`.trim()}>\n {showTitle ? (\n <div className={styles.header}>\n <PageHeader\n title={title}\n description={description}\n icon={icon}\n extra={headerExtra}\n onBack={onBack}\n onSettings={onSettings}\n brand={brand}\n onBrandClick={onBrandClick}\n brandTitle={brandTitle}\n brandAriaLabel={brandAriaLabel}\n onViewerToggle={onViewerToggle}\n viewerVisible={viewerVisible}\n viewerShowLabel={viewerShowLabel}\n viewerHideLabel={viewerHideLabel}\n />\n </div>\n ) : null}\n\n {subTabs?.length ? (\n <div className={styles.subTabs} role=\"tablist\" aria-label={`${title} sections`}>\n {subTabs.map((tab) => (\n <button\n key={tab.id}\n onClick={() => onSubTabChange?.(tab.id)}\n className={`${styles.subTabButton} ${activeSubTab === tab.id ? styles.subTabButtonActive : \"\"}`.trim()}\n type=\"button\"\n role=\"tab\"\n aria-selected={activeSubTab === tab.id}\n >\n {tab.label}\n </button>\n ))}\n </div>\n ) : null}\n\n <div className={styles.content}>\n {loading ? <div className={styles.loading}>Loading...</div> : children ?? null}\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface QuickInfoItem {
|
|
3
|
+
icon?: React.ReactNode;
|
|
4
|
+
label: string;
|
|
5
|
+
value: string | number;
|
|
6
|
+
valueColor?: "default" | "success" | "warning" | "danger";
|
|
7
|
+
mono?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface StorageProgress {
|
|
10
|
+
used: number;
|
|
11
|
+
limit: number;
|
|
12
|
+
}
|
|
13
|
+
export interface QuickInfoCardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
14
|
+
items: QuickInfoItem[];
|
|
15
|
+
storageProgress?: StorageProgress;
|
|
16
|
+
showCornerBrackets?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function QuickInfoCard({ items, storageProgress, className, showCornerBrackets, ...props }: QuickInfoCardProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export default QuickInfoCard;
|
|
20
|
+
//# sourceMappingURL=QuickInfoCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QuickInfoCard.d.ts","sourceRoot":"","sources":["../../src/components/QuickInfoCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC1D,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAmB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC9E,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAeD,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,eAAe,EACf,SAAc,EACd,kBAAyB,EACzB,GAAG,KAAK,EACT,EAAE,kBAAkB,2CAiEpB;AAED,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import styles from "./QuickInfoCard.module.css";
|
|
3
|
+
function formatFileSize(bytes) {
|
|
4
|
+
if (bytes === 0) {
|
|
5
|
+
return "0 Bytes";
|
|
6
|
+
}
|
|
7
|
+
const base = 1024;
|
|
8
|
+
const sizes = ["Bytes", "KB", "MB", "GB"];
|
|
9
|
+
const unitIndex = Math.floor(Math.log(bytes) / Math.log(base));
|
|
10
|
+
return `${parseFloat((bytes / Math.pow(base, unitIndex)).toFixed(2))} ${sizes[unitIndex]}`;
|
|
11
|
+
}
|
|
12
|
+
export function QuickInfoCard({ items, storageProgress, className = "", showCornerBrackets = true, ...props }) {
|
|
13
|
+
const storageRatio = storageProgress
|
|
14
|
+
? storageProgress.used / Math.max(storageProgress.limit, 1)
|
|
15
|
+
: 0;
|
|
16
|
+
const storageToneClass = storageRatio > 0.9
|
|
17
|
+
? styles.storageDanger
|
|
18
|
+
: storageRatio > 0.7
|
|
19
|
+
? styles.storageWarning
|
|
20
|
+
: "";
|
|
21
|
+
const getValueToneClass = (color) => {
|
|
22
|
+
switch (color) {
|
|
23
|
+
case "success":
|
|
24
|
+
return styles.valueSuccess;
|
|
25
|
+
case "warning":
|
|
26
|
+
return styles.valueWarning;
|
|
27
|
+
case "danger":
|
|
28
|
+
return styles.valueDanger;
|
|
29
|
+
default:
|
|
30
|
+
return "";
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
return (_jsxs("div", { className: `${styles.card} ${showCornerBrackets ? styles.cardWithBrackets : ""} ${className}`.trim(), ...props, children: [items.map((item, index) => (_jsxs("div", { className: styles.item, children: [item.icon ? _jsx("div", { className: styles.icon, children: item.icon }) : null, _jsxs("div", { className: styles.info, children: [_jsx("span", { className: styles.label, children: item.label }), _jsx("span", { className: `${styles.value} ${item.mono ? styles.valueMono : ""} ${getValueToneClass(item.valueColor)}`.trim(), children: item.value })] })] }, `${item.label}-${index}`))), storageProgress ? (_jsxs("div", { className: styles.storageProgress, children: [_jsxs("div", { className: styles.storageProgressLabel, children: [_jsx("span", { children: "Storage" }), _jsxs("span", { className: styles.storageProgressValue, children: [formatFileSize(storageProgress.used), " /", " ", formatFileSize(storageProgress.limit)] })] }), _jsx("div", { className: styles.storageProgressBar, children: _jsx("div", { className: `${styles.storageProgressFill} ${storageToneClass}`.trim(), style: {
|
|
34
|
+
"--storage-progress-width": `${Math.min(storageRatio * 100, 100)}%`,
|
|
35
|
+
} }) })] })) : null] }));
|
|
36
|
+
}
|
|
37
|
+
export default QuickInfoCard;
|
|
38
|
+
//# sourceMappingURL=QuickInfoCard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QuickInfoCard.js","sourceRoot":"","sources":["../../src/components/QuickInfoCard.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from \"react\";\n\nimport styles from \"./QuickInfoCard.module.css\";\n\nexport interface QuickInfoItem {\n icon?: React.ReactNode;\n label: string;\n value: string | number;\n valueColor?: \"default\" | \"success\" | \"warning\" | \"danger\";\n mono?: boolean;\n}\n\nexport interface StorageProgress {\n used: number;\n limit: number;\n}\n\nexport interface QuickInfoCardProps extends React.HTMLAttributes<HTMLDivElement> {\n items: QuickInfoItem[];\n storageProgress?: StorageProgress;\n showCornerBrackets?: boolean;\n}\n\nfunction formatFileSize(bytes: number) {\n if (bytes === 0) {\n return \"0 Bytes\";\n }\n\n const base = 1024;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\"];\n const unitIndex = Math.floor(Math.log(bytes) / Math.log(base));\n return `${parseFloat((bytes / Math.pow(base, unitIndex)).toFixed(2))} ${\n sizes[unitIndex]\n }`;\n}\n\nexport function QuickInfoCard({\n items,\n storageProgress,\n className = \"\",\n showCornerBrackets = true,\n ...props\n}: QuickInfoCardProps) {\n const storageRatio = storageProgress\n ? storageProgress.used / Math.max(storageProgress.limit, 1)\n : 0;\n const storageToneClass =\n storageRatio > 0.9\n ? styles.storageDanger\n : storageRatio > 0.7\n ? styles.storageWarning\n : \"\";\n\n const getValueToneClass = (color?: QuickInfoItem[\"valueColor\"]) => {\n switch (color) {\n case \"success\":\n return styles.valueSuccess;\n case \"warning\":\n return styles.valueWarning;\n case \"danger\":\n return styles.valueDanger;\n default:\n return \"\";\n }\n };\n\n return (\n <div\n className={`${styles.card} ${showCornerBrackets ? styles.cardWithBrackets : \"\"} ${className}`.trim()}\n {...props}\n >\n {items.map((item, index) => (\n <div key={`${item.label}-${index}`} className={styles.item}>\n {item.icon ? <div className={styles.icon}>{item.icon}</div> : null}\n <div className={styles.info}>\n <span className={styles.label}>{item.label}</span>\n <span\n className={`${styles.value} ${item.mono ? styles.valueMono : \"\"} ${getValueToneClass(item.valueColor)}`.trim()}\n >\n {item.value}\n </span>\n </div>\n </div>\n ))}\n {storageProgress ? (\n <div className={styles.storageProgress}>\n <div className={styles.storageProgressLabel}>\n <span>Storage</span>\n <span className={styles.storageProgressValue}>\n {formatFileSize(storageProgress.used)} /{\" \"}\n {formatFileSize(storageProgress.limit)}\n </span>\n </div>\n <div className={styles.storageProgressBar}>\n <div\n className={`${styles.storageProgressFill} ${storageToneClass}`.trim()}\n style={\n {\n \"--storage-progress-width\": `${Math.min(storageRatio * 100, 100)}%`,\n } as React.CSSProperties\n }\n />\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\nexport default QuickInfoCard;\n"]}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
.card {
|
|
2
|
+
display: flex;
|
|
3
|
+
gap: 1.5rem;
|
|
4
|
+
padding: 1rem 1.5rem;
|
|
5
|
+
margin: 0.75rem;
|
|
6
|
+
background: var(--bg-secondary);
|
|
7
|
+
border: 1px solid var(--border-color);
|
|
8
|
+
flex-wrap: wrap;
|
|
9
|
+
position: relative;
|
|
10
|
+
overflow: visible;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.cardWithBrackets::before {
|
|
14
|
+
content: "";
|
|
15
|
+
position: absolute;
|
|
16
|
+
top: -0.5rem;
|
|
17
|
+
left: -0.5rem;
|
|
18
|
+
width: 0.5rem;
|
|
19
|
+
height: 0.5rem;
|
|
20
|
+
border-top: 1px solid var(--border-color);
|
|
21
|
+
border-left: 1px solid var(--border-color);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.cardWithBrackets::after {
|
|
25
|
+
content: "";
|
|
26
|
+
position: absolute;
|
|
27
|
+
bottom: -0.5rem;
|
|
28
|
+
right: -0.5rem;
|
|
29
|
+
width: 0.5rem;
|
|
30
|
+
height: 0.5rem;
|
|
31
|
+
border-bottom: 1px solid var(--border-color);
|
|
32
|
+
border-right: 1px solid var(--border-color);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.item {
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
gap: 0.75rem;
|
|
39
|
+
flex: 1;
|
|
40
|
+
min-width: 150px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.icon {
|
|
44
|
+
display: grid;
|
|
45
|
+
place-items: center;
|
|
46
|
+
flex-shrink: 0;
|
|
47
|
+
color: var(--accent-primary);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.icon :global(svg) {
|
|
51
|
+
width: 1.25rem;
|
|
52
|
+
height: 1.25rem;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.info {
|
|
56
|
+
display: flex;
|
|
57
|
+
flex-direction: column;
|
|
58
|
+
gap: 0.125rem;
|
|
59
|
+
flex: 1;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.label {
|
|
63
|
+
color: var(--text-secondary);
|
|
64
|
+
font-size: 0.6875rem;
|
|
65
|
+
font-weight: 500;
|
|
66
|
+
text-transform: uppercase;
|
|
67
|
+
letter-spacing: 0.05em;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.value {
|
|
71
|
+
color: var(--text-primary);
|
|
72
|
+
font-size: 1rem;
|
|
73
|
+
font-weight: 600;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.valueMono {
|
|
77
|
+
font-family: var(--font-mono);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.valueSuccess {
|
|
81
|
+
color: var(--color-success, #10b981);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.valueWarning {
|
|
85
|
+
color: var(--color-warning, #f59e0b);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.valueDanger {
|
|
89
|
+
color: var(--color-error, #ef4444);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.storageProgress {
|
|
93
|
+
flex: 1;
|
|
94
|
+
min-width: 200px;
|
|
95
|
+
display: flex;
|
|
96
|
+
flex-direction: column;
|
|
97
|
+
gap: 0.375rem;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.storageProgressLabel {
|
|
101
|
+
display: flex;
|
|
102
|
+
justify-content: space-between;
|
|
103
|
+
color: var(--text-secondary);
|
|
104
|
+
font-size: 0.6875rem;
|
|
105
|
+
font-weight: 500;
|
|
106
|
+
text-transform: uppercase;
|
|
107
|
+
letter-spacing: 0.05em;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.storageProgressValue {
|
|
111
|
+
color: var(--text-primary);
|
|
112
|
+
font-family: var(--font-mono);
|
|
113
|
+
font-weight: 600;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.storageProgressBar {
|
|
117
|
+
height: 8px;
|
|
118
|
+
background: color-mix(in srgb, var(--bg-primary) 82%, transparent);
|
|
119
|
+
border-radius: 4px;
|
|
120
|
+
overflow: hidden;
|
|
121
|
+
border: 1px solid var(--border-color);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.storageProgressFill {
|
|
125
|
+
height: 100%;
|
|
126
|
+
width: var(--storage-progress-width, 0%);
|
|
127
|
+
background: var(--accent-primary);
|
|
128
|
+
border-radius: 3px;
|
|
129
|
+
transition: width 220ms ease;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.storageWarning {
|
|
133
|
+
background: var(--color-warning, #f59e0b);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.storageDanger {
|
|
137
|
+
background: var(--color-error, #ef4444);
|
|
138
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { SteezIconProps } from "@steez-ui/icons";
|
|
3
|
+
export interface RuntimeOrbitNode {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
icon: React.ComponentType<SteezIconProps>;
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
}
|
|
10
|
+
export interface RuntimeOrbitDiagramProps {
|
|
11
|
+
nodes: RuntimeOrbitNode[];
|
|
12
|
+
className?: string;
|
|
13
|
+
durationSeconds?: number;
|
|
14
|
+
pathOrder?: readonly string[];
|
|
15
|
+
iconSize?: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function RuntimeOrbitDiagram({ nodes, className, durationSeconds, pathOrder, iconSize, }: RuntimeOrbitDiagramProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export default RuntimeOrbitDiagram;
|
|
19
|
+
//# sourceMappingURL=RuntimeOrbitDiagram.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RuntimeOrbitDiagram.d.ts","sourceRoot":"","sources":["../../src/components/RuntimeOrbitDiagram.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAItD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAcD,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,SAAc,EACd,eAAqB,EACrB,SAAS,EACT,QAAa,GACd,EAAE,wBAAwB,2CA4E1B;AAED,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import styles from "./RuntimeOrbitDiagram.module.css";
|
|
4
|
+
function buildPath(points) {
|
|
5
|
+
if (points.length === 0) {
|
|
6
|
+
return "";
|
|
7
|
+
}
|
|
8
|
+
return `${points
|
|
9
|
+
.map((point, index) => `${index === 0 ? "M" : "L"} ${point.x.toFixed(2)} ${point.y.toFixed(2)}`)
|
|
10
|
+
.join(" ")} Z`;
|
|
11
|
+
}
|
|
12
|
+
export function RuntimeOrbitDiagram({ nodes, className = "", durationSeconds = 5.4, pathOrder, iconSize = 22, }) {
|
|
13
|
+
const orderedNodes = React.useMemo(() => {
|
|
14
|
+
if (!pathOrder?.length) {
|
|
15
|
+
return nodes;
|
|
16
|
+
}
|
|
17
|
+
const nodeMap = new Map(nodes.map((node) => [node.id, node]));
|
|
18
|
+
const sequence = pathOrder
|
|
19
|
+
.map((id) => nodeMap.get(id))
|
|
20
|
+
.filter((node) => Boolean(node));
|
|
21
|
+
return sequence.length === nodes.length ? sequence : nodes;
|
|
22
|
+
}, [nodes, pathOrder]);
|
|
23
|
+
const pathD = React.useMemo(() => buildPath(orderedNodes), [orderedNodes]);
|
|
24
|
+
const nodeSequenceIndex = React.useMemo(() => new Map(orderedNodes.map((node, index) => [node.id, index])), [orderedNodes]);
|
|
25
|
+
return (_jsxs("div", { className: `${styles.root} ${className}`.trim(), style: { "--orbit-duration": `${durationSeconds}s` }, children: [_jsxs("svg", { className: styles.svg, viewBox: "0 0 100 100", preserveAspectRatio: "none", "aria-hidden": "true", children: [pathD ? _jsx("path", { className: styles.track, d: pathD, pathLength: 100 }) : null, pathD ? _jsx("path", { className: styles.pathLine, d: pathD, pathLength: 100 }) : null, pathD ? (_jsx("circle", { className: styles.dot, cx: "0", cy: "0", r: "1.45", children: _jsx("animateMotion", { calcMode: "linear", dur: `${durationSeconds}s`, path: pathD, repeatCount: "indefinite" }) })) : null] }), nodes.map((node) => {
|
|
26
|
+
const IconComponent = node.icon;
|
|
27
|
+
const sequenceIndex = nodeSequenceIndex.get(node.id) ?? 0;
|
|
28
|
+
const nodeDelayMs = Math.round((durationSeconds * 1000 * sequenceIndex) /
|
|
29
|
+
Math.max(orderedNodes.length, 1) -
|
|
30
|
+
120);
|
|
31
|
+
return (_jsxs("div", { className: styles.node, style: {
|
|
32
|
+
"--node-x": `${node.x}%`,
|
|
33
|
+
"--node-y": `${node.y}%`,
|
|
34
|
+
"--node-delay": `${nodeDelayMs}ms`,
|
|
35
|
+
}, title: node.label, children: [_jsx("div", { className: styles.nodeInner, children: _jsx(IconComponent, { width: iconSize, height: iconSize }) }), _jsx("span", { className: styles.srOnly, children: node.label })] }, node.id));
|
|
36
|
+
})] }));
|
|
37
|
+
}
|
|
38
|
+
export default RuntimeOrbitDiagram;
|
|
39
|
+
//# sourceMappingURL=RuntimeOrbitDiagram.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RuntimeOrbitDiagram.js","sourceRoot":"","sources":["../../src/components/RuntimeOrbitDiagram.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from \"react\";\n\nimport type { SteezIconProps } from \"@steez-ui/icons\";\n\nimport styles from \"./RuntimeOrbitDiagram.module.css\";\n\nexport interface RuntimeOrbitNode {\n id: string;\n label: string;\n icon: React.ComponentType<SteezIconProps>;\n x: number;\n y: number;\n}\n\nexport interface RuntimeOrbitDiagramProps {\n nodes: RuntimeOrbitNode[];\n className?: string;\n durationSeconds?: number;\n pathOrder?: readonly string[];\n iconSize?: number;\n}\n\nfunction buildPath(points: RuntimeOrbitNode[]) {\n if (points.length === 0) {\n return \"\";\n }\n\n return `${points\n .map((point, index) =>\n `${index === 0 ? \"M\" : \"L\"} ${point.x.toFixed(2)} ${point.y.toFixed(2)}`,\n )\n .join(\" \")} Z`;\n}\n\nexport function RuntimeOrbitDiagram({\n nodes,\n className = \"\",\n durationSeconds = 5.4,\n pathOrder,\n iconSize = 22,\n}: RuntimeOrbitDiagramProps) {\n const orderedNodes = React.useMemo(() => {\n if (!pathOrder?.length) {\n return nodes;\n }\n\n const nodeMap = new Map(nodes.map((node) => [node.id, node] as const));\n const sequence = pathOrder\n .map((id) => nodeMap.get(id))\n .filter((node): node is RuntimeOrbitNode => Boolean(node));\n\n return sequence.length === nodes.length ? sequence : nodes;\n }, [nodes, pathOrder]);\n\n const pathD = React.useMemo(() => buildPath(orderedNodes), [orderedNodes]);\n const nodeSequenceIndex = React.useMemo(\n () => new Map(orderedNodes.map((node, index) => [node.id, index] as const)),\n [orderedNodes],\n );\n\n return (\n <div\n className={`${styles.root} ${className}`.trim()}\n style={{ \"--orbit-duration\": `${durationSeconds}s` } as React.CSSProperties}\n >\n <svg\n className={styles.svg}\n viewBox=\"0 0 100 100\"\n preserveAspectRatio=\"none\"\n aria-hidden=\"true\"\n >\n {pathD ? <path className={styles.track} d={pathD} pathLength={100} /> : null}\n {pathD ? <path className={styles.pathLine} d={pathD} pathLength={100} /> : null}\n {pathD ? (\n <circle className={styles.dot} cx=\"0\" cy=\"0\" r=\"1.45\">\n <animateMotion\n calcMode=\"linear\"\n dur={`${durationSeconds}s`}\n path={pathD}\n repeatCount=\"indefinite\"\n />\n </circle>\n ) : null}\n </svg>\n\n {nodes.map((node) => {\n const IconComponent = node.icon;\n const sequenceIndex = nodeSequenceIndex.get(node.id) ?? 0;\n const nodeDelayMs = Math.round(\n (durationSeconds * 1000 * sequenceIndex) /\n Math.max(orderedNodes.length, 1) -\n 120,\n );\n\n return (\n <div\n key={node.id}\n className={styles.node}\n style={\n {\n \"--node-x\": `${node.x}%`,\n \"--node-y\": `${node.y}%`,\n \"--node-delay\": `${nodeDelayMs}ms`,\n } as React.CSSProperties\n }\n title={node.label}\n >\n <div className={styles.nodeInner}>\n <IconComponent width={iconSize} height={iconSize} />\n </div>\n <span className={styles.srOnly}>{node.label}</span>\n </div>\n );\n })}\n </div>\n );\n}\n\nexport default RuntimeOrbitDiagram;\n"]}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
--orbit-duration: 5.4s;
|
|
3
|
+
|
|
4
|
+
position: relative;
|
|
5
|
+
width: min(100%, 38rem);
|
|
6
|
+
aspect-ratio: 1;
|
|
7
|
+
min-height: 22rem;
|
|
8
|
+
isolation: isolate;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.svg {
|
|
12
|
+
width: 100%;
|
|
13
|
+
height: 100%;
|
|
14
|
+
display: block;
|
|
15
|
+
overflow: visible;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.track {
|
|
19
|
+
fill: none;
|
|
20
|
+
stroke: color-mix(in srgb, var(--text-primary) 14%, transparent);
|
|
21
|
+
stroke-width: 0.8;
|
|
22
|
+
stroke-linecap: round;
|
|
23
|
+
stroke-linejoin: round;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.pathLine {
|
|
27
|
+
fill: none;
|
|
28
|
+
stroke: color-mix(in srgb, var(--accent-primary) 88%, transparent);
|
|
29
|
+
stroke-width: 1.35;
|
|
30
|
+
stroke-linecap: round;
|
|
31
|
+
stroke-linejoin: round;
|
|
32
|
+
stroke-dasharray: 14 86;
|
|
33
|
+
animation: orbitPath var(--orbit-duration) linear infinite;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.node {
|
|
37
|
+
position: absolute;
|
|
38
|
+
top: var(--node-y);
|
|
39
|
+
left: var(--node-x);
|
|
40
|
+
width: clamp(4.15rem, 8vw, 4.95rem);
|
|
41
|
+
aspect-ratio: 1;
|
|
42
|
+
translate: -50% -50%;
|
|
43
|
+
display: grid;
|
|
44
|
+
place-items: center;
|
|
45
|
+
border-radius: 999px;
|
|
46
|
+
color: color-mix(in srgb, var(--text-secondary) 92%, transparent);
|
|
47
|
+
border: 1px solid color-mix(in srgb, var(--border-color) 78%, transparent);
|
|
48
|
+
background: color-mix(in srgb, var(--bg-secondary) 94%, transparent);
|
|
49
|
+
box-shadow: 0 0 0 1px color-mix(in srgb, var(--bg-primary) 28%, transparent);
|
|
50
|
+
animation: orbitPulse var(--orbit-duration) linear infinite;
|
|
51
|
+
animation-delay: var(--node-delay);
|
|
52
|
+
transition:
|
|
53
|
+
border-color var(--tile-hover-duration, 220ms) ease,
|
|
54
|
+
transform var(--tile-hover-duration, 220ms) ease,
|
|
55
|
+
background-color var(--tile-hover-duration, 220ms) ease;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.node:hover {
|
|
59
|
+
color: var(--text-primary);
|
|
60
|
+
border-color: color-mix(in srgb, var(--accent-primary) 46%, var(--border-color));
|
|
61
|
+
transform: translateY(-1px);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.nodeInner {
|
|
65
|
+
width: calc(100% - 10px);
|
|
66
|
+
height: calc(100% - 10px);
|
|
67
|
+
display: grid;
|
|
68
|
+
place-items: center;
|
|
69
|
+
border-radius: inherit;
|
|
70
|
+
background: color-mix(in srgb, var(--bg-primary) 96%, transparent);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.nodeInner svg {
|
|
74
|
+
width: 48%;
|
|
75
|
+
height: 48%;
|
|
76
|
+
color: currentColor;
|
|
77
|
+
opacity: 0.88;
|
|
78
|
+
transform: scale(0.86);
|
|
79
|
+
transition:
|
|
80
|
+
opacity var(--tile-hover-duration, 220ms) ease,
|
|
81
|
+
transform var(--tile-hover-duration, 220ms) ease,
|
|
82
|
+
color var(--tile-hover-duration, 220ms) ease;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.node:hover .nodeInner svg {
|
|
86
|
+
opacity: 1;
|
|
87
|
+
transform: scale(0.92);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.dot {
|
|
91
|
+
fill: var(--accent-primary);
|
|
92
|
+
filter: drop-shadow(
|
|
93
|
+
0 0 8px color-mix(in srgb, var(--accent-primary) 32%, transparent)
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.srOnly {
|
|
98
|
+
position: absolute;
|
|
99
|
+
width: 1px;
|
|
100
|
+
height: 1px;
|
|
101
|
+
padding: 0;
|
|
102
|
+
margin: -1px;
|
|
103
|
+
overflow: hidden;
|
|
104
|
+
clip: rect(0, 0, 0, 0);
|
|
105
|
+
white-space: nowrap;
|
|
106
|
+
border: 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@keyframes orbitPath {
|
|
110
|
+
from {
|
|
111
|
+
stroke-dashoffset: 0;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
to {
|
|
115
|
+
stroke-dashoffset: -100;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@keyframes orbitPulse {
|
|
120
|
+
0%,
|
|
121
|
+
4%,
|
|
122
|
+
16%,
|
|
123
|
+
100% {
|
|
124
|
+
color: color-mix(in srgb, var(--text-secondary) 92%, transparent);
|
|
125
|
+
border-color: color-mix(in srgb, var(--border-color) 78%, transparent);
|
|
126
|
+
background: color-mix(in srgb, var(--bg-secondary) 94%, transparent);
|
|
127
|
+
box-shadow: 0 0 0 1px color-mix(in srgb, var(--bg-primary) 28%, transparent);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
6%,
|
|
131
|
+
13% {
|
|
132
|
+
color: var(--text-primary);
|
|
133
|
+
border-color: color-mix(in srgb, var(--accent-primary) 64%, var(--border-color));
|
|
134
|
+
background: color-mix(in srgb, var(--accent-primary) 12%, var(--bg-secondary));
|
|
135
|
+
box-shadow:
|
|
136
|
+
0 0 0 1px color-mix(in srgb, var(--accent-primary) 24%, transparent),
|
|
137
|
+
0 0 22px color-mix(in srgb, var(--accent-primary) 18%, transparent);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@media (max-width: 720px) {
|
|
142
|
+
.root {
|
|
143
|
+
min-height: 18rem;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.node {
|
|
147
|
+
width: clamp(3.55rem, 17vw, 4.25rem);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@media (prefers-reduced-motion: reduce) {
|
|
152
|
+
.pathLine,
|
|
153
|
+
.node {
|
|
154
|
+
animation: none;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.dot {
|
|
158
|
+
display: none;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface SectionProps extends Omit<React.HTMLAttributes<HTMLElement>, "title"> {
|
|
3
|
+
title?: React.ReactNode;
|
|
4
|
+
titleClassName?: string;
|
|
5
|
+
contentClassName?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function Section({ title, children, className, titleClassName, contentClassName, ...props }: SectionProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export default Section;
|
|
9
|
+
//# sourceMappingURL=Section.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Section.d.ts","sourceRoot":"","sources":["../../src/components/Section.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,WAAW,YACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IACxD,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,OAAO,CAAC,EACtB,KAAK,EACL,QAAQ,EACR,SAAc,EACd,cAAmB,EACnB,gBAAqB,EACrB,GAAG,KAAK,EACT,EAAE,YAAY,2CAWd;AAED,eAAe,OAAO,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import styles from "./Section.module.css";
|
|
3
|
+
export function Section({ title, children, className = "", titleClassName = "", contentClassName = "", ...props }) {
|
|
4
|
+
return (_jsxs("section", { className: `${styles.section} ${className}`.trim(), ...props, children: [title ? (_jsx("h3", { className: `${styles.title} ${titleClassName}`.trim(), children: title })) : null, _jsx("div", { className: `${styles.content} ${contentClassName}`.trim(), children: children })] }));
|
|
5
|
+
}
|
|
6
|
+
export default Section;
|
|
7
|
+
//# sourceMappingURL=Section.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Section.js","sourceRoot":"","sources":["../../src/components/Section.tsx"],"names":[],"mappings":";AAEA,OAAO,MAAM,MAAM,sBAAsB,CAAC;AAS1C,MAAM,UAAU,OAAO,CAAC,EACtB,KAAK,EACL,QAAQ,EACR,SAAS,GAAG,EAAE,EACd,cAAc,GAAG,EAAE,EACnB,gBAAgB,GAAG,EAAE,EACrB,GAAG,KAAK,EACK;IACb,OAAO,CACL,mBAAS,SAAS,EAAE,GAAG,MAAM,CAAC,OAAO,IAAI,SAAS,EAAE,CAAC,IAAI,EAAE,KAAM,KAAK,aACnE,KAAK,CAAC,CAAC,CAAC,CACP,aAAI,SAAS,EAAE,GAAG,MAAM,CAAC,KAAK,IAAI,cAAc,EAAE,CAAC,IAAI,EAAE,YAAG,KAAK,GAAM,CACxE,CAAC,CAAC,CAAC,IAAI,EACR,cAAK,SAAS,EAAE,GAAG,MAAM,CAAC,OAAO,IAAI,gBAAgB,EAAE,CAAC,IAAI,EAAE,YAC3D,QAAQ,GACL,IACE,CACX,CAAC;AACJ,CAAC;AAED,eAAe,OAAO,CAAC","sourcesContent":["import React from \"react\";\n\nimport styles from \"./Section.module.css\";\n\nexport interface SectionProps\n extends Omit<React.HTMLAttributes<HTMLElement>, \"title\"> {\n title?: React.ReactNode;\n titleClassName?: string;\n contentClassName?: string;\n}\n\nexport function Section({\n title,\n children,\n className = \"\",\n titleClassName = \"\",\n contentClassName = \"\",\n ...props\n}: SectionProps) {\n return (\n <section className={`${styles.section} ${className}`.trim()} {...props}>\n {title ? (\n <h3 className={`${styles.title} ${titleClassName}`.trim()}>{title}</h3>\n ) : null}\n <div className={`${styles.content} ${contentClassName}`.trim()}>\n {children}\n </div>\n </section>\n );\n}\n\nexport default Section;\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
.section {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
gap: 0.85rem;
|
|
5
|
+
margin-bottom: 1.5rem;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.title {
|
|
9
|
+
margin: 0;
|
|
10
|
+
color: var(--text-primary);
|
|
11
|
+
font-family: var(--font-mono);
|
|
12
|
+
font-size: 0.9rem;
|
|
13
|
+
font-weight: 600;
|
|
14
|
+
letter-spacing: 0.08em;
|
|
15
|
+
text-transform: uppercase;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.content {
|
|
19
|
+
min-width: 0;
|
|
20
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface SectionHeaderProps {
|
|
3
|
+
title: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
actions?: React.ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function SectionHeader({ title, description, actions, className, }: SectionHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export default SectionHeader;
|
|
10
|
+
//# sourceMappingURL=SectionHeader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SectionHeader.d.ts","sourceRoot":"","sources":["../../src/components/SectionHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,WAAW,EACX,OAAO,EACP,SAAc,GACf,EAAE,kBAAkB,2CAcpB;AAED,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import styles from "./SectionHeader.module.css";
|
|
3
|
+
export function SectionHeader({ title, description, actions, className = "", }) {
|
|
4
|
+
return (_jsx("div", { className: `${styles.sectionHeader} ${className}`.trim(), children: _jsxs("div", { className: styles.headerContent, children: [_jsxs("div", { className: styles.textContent, children: [_jsx("h2", { className: styles.title, children: title }), description ? (_jsx("p", { className: styles.description, children: description })) : null] }), actions ? _jsx("div", { className: styles.actions, children: actions }) : null] }) }));
|
|
5
|
+
}
|
|
6
|
+
export default SectionHeader;
|
|
7
|
+
//# sourceMappingURL=SectionHeader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SectionHeader.js","sourceRoot":"","sources":["../../src/components/SectionHeader.tsx"],"names":[],"mappings":";AAEA,OAAO,MAAM,MAAM,4BAA4B,CAAC;AAShD,MAAM,UAAU,aAAa,CAAC,EAC5B,KAAK,EACL,WAAW,EACX,OAAO,EACP,SAAS,GAAG,EAAE,GACK;IACnB,OAAO,CACL,cAAK,SAAS,EAAE,GAAG,MAAM,CAAC,aAAa,IAAI,SAAS,EAAE,CAAC,IAAI,EAAE,YAC3D,eAAK,SAAS,EAAE,MAAM,CAAC,aAAa,aAClC,eAAK,SAAS,EAAE,MAAM,CAAC,WAAW,aAChC,aAAI,SAAS,EAAE,MAAM,CAAC,KAAK,YAAG,KAAK,GAAM,EACxC,WAAW,CAAC,CAAC,CAAC,CACb,YAAG,SAAS,EAAE,MAAM,CAAC,WAAW,YAAG,WAAW,GAAK,CACpD,CAAC,CAAC,CAAC,IAAI,IACJ,EACL,OAAO,CAAC,CAAC,CAAC,cAAK,SAAS,EAAE,MAAM,CAAC,OAAO,YAAG,OAAO,GAAO,CAAC,CAAC,CAAC,IAAI,IAC7D,GACF,CACP,CAAC;AACJ,CAAC;AAED,eAAe,aAAa,CAAC","sourcesContent":["import React from \"react\";\n\nimport styles from \"./SectionHeader.module.css\";\n\nexport interface SectionHeaderProps {\n title: string;\n description?: string;\n actions?: React.ReactNode;\n className?: string;\n}\n\nexport function SectionHeader({\n title,\n description,\n actions,\n className = \"\",\n}: SectionHeaderProps) {\n return (\n <div className={`${styles.sectionHeader} ${className}`.trim()}>\n <div className={styles.headerContent}>\n <div className={styles.textContent}>\n <h2 className={styles.title}>{title}</h2>\n {description ? (\n <p className={styles.description}>{description}</p>\n ) : null}\n </div>\n {actions ? <div className={styles.actions}>{actions}</div> : null}\n </div>\n </div>\n );\n}\n\nexport default SectionHeader;\n"]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
.sectionHeader {
|
|
2
|
+
background: var(--bg-secondary);
|
|
3
|
+
border: 1px solid var(--border-color);
|
|
4
|
+
border-radius: 8px;
|
|
5
|
+
padding: 1rem 1.25rem;
|
|
6
|
+
margin-bottom: 1.25rem;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.headerContent {
|
|
10
|
+
display: flex;
|
|
11
|
+
justify-content: space-between;
|
|
12
|
+
align-items: center;
|
|
13
|
+
gap: 1rem;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.textContent {
|
|
17
|
+
flex: 1;
|
|
18
|
+
min-width: 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.title {
|
|
22
|
+
margin: 0 0 0.25rem;
|
|
23
|
+
color: var(--text-primary);
|
|
24
|
+
font-family: var(--font-mono);
|
|
25
|
+
font-size: 1rem;
|
|
26
|
+
font-weight: 600;
|
|
27
|
+
letter-spacing: 0.06em;
|
|
28
|
+
text-transform: uppercase;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.description {
|
|
32
|
+
margin: 0;
|
|
33
|
+
color: var(--text-secondary);
|
|
34
|
+
font-size: 0.8125rem;
|
|
35
|
+
line-height: 1.5;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.actions {
|
|
39
|
+
display: flex;
|
|
40
|
+
align-items: center;
|
|
41
|
+
gap: 0.5rem;
|
|
42
|
+
flex-shrink: 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@media (max-width: 640px) {
|
|
46
|
+
.headerContent {
|
|
47
|
+
flex-direction: column;
|
|
48
|
+
align-items: stretch;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.actions {
|
|
52
|
+
justify-content: flex-end;
|
|
53
|
+
}
|
|
54
|
+
}
|