@dataverse-kit/surface-kit 0.2.0 → 0.3.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/sizePresets.ts","../src/core/columns.ts","../src/responsive/breakpoints.ts","../src/responsive/builders.ts","../src/tokens/tokens.ts","../src/tokens/density.ts","../src/hooks/useContainerSize.ts","../src/hooks/useContainerWidth.ts","../src/hooks/useContainerBreakpoint.ts","../src/hooks/useResponsiveValue.ts","../src/hooks/useMediaQuery.ts","../src/hooks/useDensity.ts","../src/v9/theme.ts","../src/v9/containers/FormSurface.tsx","../src/v9/containers/PageSurface.tsx","../src/v9/containers/Section.tsx","../src/v9/containers/SectionHeader.tsx","../src/v9/containers/SectionCard.tsx","../src/v9/containers/FormHeader.tsx","../src/v9/containers/PivotSurface.tsx","../src/v9/containers/CommandSurface.tsx","../src/v9/containers/ActionBar.tsx","../src/v9/containers/Footer.tsx","../src/v9/overlays/FormDialogSurface.tsx","../src/v9/overlays/ModalSurface.tsx","../src/v9/overlays/PanelSurface.tsx","../src/v9/overlays/CalloutSurface.tsx","../src/v9/overlays/TooltipSurface.tsx"],"sourcesContent":["// Pure-TS sizing scalars for overlay surfaces. The SINGLE SOURCE of the numbers\n// that both surface-kit's runtime overlays AND the export-engine codegen use, so a\n// Dialog is 1200px wide in exactly one place. Framework-agnostic (no react/@fluentui).\n//\n// Values mirror export-engine/src/generators/FormCodeGenerator.ts (v8 branches):\n// dialog: default width 1200; height <=100 -> `${h}vh` else '95vh'\n// panel: kind = (width ?? 480) > 500 ? 'medium' : 'custom'; custom width = width ?? 480\n// callout (form-type): default width 320; directionalHint 'bottomLeftEdge'\n// v1c wires export-engine to import these; a byte-identical emission test guards drift.\n\n// --- Dialog --------------------------------------------------------------------\n\nexport type DialogSizePreset = 'sm' | 'md' | 'lg' | 'xl' | 'fullscreen';\n\n// NOTE: only the lg = 1200 default and an explicit `width` are the shared-with-codegen\n// contract (export-engine does `width ?? 1200`). The sm/md/xl/fullscreen presets are\n// surface-kit runtime conveniences with no codegen counterpart — v1c does NOT consume them.\nexport const DIALOG_SIZE_PX = {\n sm: 600,\n md: 900,\n lg: 1200,\n xl: 1600,\n} as const;\n\n/** Resolved dialog width in px. Explicit `width` wins; else the preset (default lg = 1200, the codegen default). */\nexport function dialogWidthPx(opts: { width?: number; size?: DialogSizePreset } = {}): number {\n if (typeof opts.width === 'number') return opts.width;\n const size = opts.size ?? 'lg';\n // fullscreen is clamped by 95vw at the CSS layer; fall back to the largest preset for the px hint.\n if (size === 'fullscreen') return DIALOG_SIZE_PX.xl;\n return DIALOG_SIZE_PX[size];\n}\n\n/** Dialog width as a CSS value — '95vw' for the fullscreen preset (no explicit width), else `${px}px`. */\nexport function dialogWidthCss(opts: { width?: number; size?: DialogSizePreset } = {}): string {\n if (opts.size === 'fullscreen' && opts.width == null) return '95vw';\n return `${dialogWidthPx(opts)}px`;\n}\n\n/** Dialog height as a CSS value. <=100 is treated as a vh percentage; otherwise the 95vh cap (codegen rule). */\nexport function dialogHeightCss(height?: number): string {\n return height != null && height <= 100 ? `${height}vh` : '95vh';\n}\n\n/** Min width for an auto-sized ModalSurface (the Track-and-Ship \"min 1000, auto\" pattern). */\nexport const MODAL_AUTOSIZE_MIN_WIDTH = 1000;\n\n// --- Panel ---------------------------------------------------------------------\n\nexport type PanelKind = 'medium' | 'custom';\nexport const PANEL_DEFAULT_WIDTH = 480;\n\n/** Codegen-parity panel kind: wide panels use Fluent `medium`, narrow ones `custom` + customWidth. */\nexport function panelKindFromWidth(width?: number): PanelKind {\n return (width ?? PANEL_DEFAULT_WIDTH) > 500 ? 'medium' : 'custom';\n}\n\n/** customWidth px for a `custom` panel. */\nexport function panelCustomWidthPx(width?: number): number {\n return width ?? PANEL_DEFAULT_WIDTH;\n}\n\n// --- Callout -------------------------------------------------------------------\n\nexport const CALLOUT_DEFAULT_WIDTH = 320;\n\n/** Form-type callout defaults (the export-engine form-callout path emits width + directionalHint only). */\nexport const calloutFormDefaults = {\n width: CALLOUT_DEFAULT_WIDTH,\n directionalHint: 'bottomLeftEdge',\n} as const;\n\nexport function calloutWidthPx(width?: number): number {\n return width ?? CALLOUT_DEFAULT_WIDTH;\n}\n","// Pure-TS column helpers shared by layouts/containers and the responsive builders.\nexport type ColumnCount = 1 | 2 | 3 | 4;\n\n/** CSS grid-template-columns for an N-column layout. Matches codegen `repeat(N, 1fr)`. */\nexport function gridTemplateForColumns(columns: ColumnCount): string {\n return `repeat(${columns}, 1fr)`;\n}\n\n/** Clamp a cell column-span to the available column count (min 1). */\nexport function clampSpan(span: number, columns: ColumnCount): number {\n if (!Number.isFinite(span)) return 1;\n return Math.max(1, Math.min(Math.round(span), columns));\n}\n","// Named responsive breakpoints (px). The 480/768 cutoffs match the export-engine\n// section/field stacking; CARD_REFLOW_WIDTH (900) matches the CardGrid reflow\n// emitter (a separate cutoff). Pure-TS (no react/@fluentui).\nexport type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\nexport const BREAKPOINTS: Record<Breakpoint, number> = {\n xs: 0,\n sm: 480,\n md: 768,\n lg: 1024,\n xl: 1366,\n};\n\n/** The card-grid reflow cutoff the codegen CardGrid emitter uses (distinct from the 480/768 field/section cutoffs). */\nexport const CARD_REFLOW_WIDTH = 900;\n\nconst DESCENDING: Breakpoint[] = ['xl', 'lg', 'md', 'sm', 'xs'];\nconst ASCENDING: Breakpoint[] = ['xs', 'sm', 'md', 'lg', 'xl'];\n\n/** Largest breakpoint whose min-width is <= width. */\nexport function resolveBreakpoint(width: number): Breakpoint {\n for (const bp of DESCENDING) {\n if (width >= BREAKPOINTS[bp]) return bp;\n }\n return 'xs';\n}\n\nexport type ResponsiveValue<T> = T | Partial<Record<Breakpoint, T>>;\n\nfunction isResponsiveMap<T>(v: ResponsiveValue<T>): v is Partial<Record<Breakpoint, T>> {\n return typeof v === 'object' && v !== null && ASCENDING.some((bp) => bp in (v as object));\n}\n\n/**\n * Resolve a responsive value at a breakpoint, cascading mobile-first: pick the\n * nearest defined value at or below `breakpoint`, else the nearest defined above.\n */\nexport function resolveResponsiveValue<T>(value: ResponsiveValue<T>, breakpoint: Breakpoint): T | undefined {\n if (!isResponsiveMap(value)) return value as T;\n const map = value;\n const idx = ASCENDING.indexOf(breakpoint);\n for (let i = idx; i >= 0; i--) {\n const v = map[ASCENDING[i]];\n if (v !== undefined) return v;\n }\n for (let i = idx + 1; i < ASCENDING.length; i++) {\n const v = map[ASCENDING[i]];\n if (v !== undefined) return v;\n }\n return undefined;\n}\n","// Pure-TS responsive style-object builders. Every responsive stacking decision in\n// surface-kit flows through here so viewport (`mode:'media'`) and container\n// (`mode:'container'`) stacking share the same 480/768 cutoffs. The numeric values\n// (gaps, minHeight, alignItems) mirror the export-engine fieldGrid/fieldRow/\n// tabSectionsGrid emitters so the eventual emitMode:'surface-kit' rewrite is parity.\n// Returned objects are structurally compatible with Fluent's `IStyle` (the `selectors`\n// shape) but typed locally so this layer stays framework-agnostic (no @fluentui import).\nimport { BREAKPOINTS } from './breakpoints';\nimport { gridTemplateForColumns, type ColumnCount } from '../core/columns';\n\nexport type StyleObject = Record<string, unknown>;\nexport type ResponsiveMode = 'media' | 'container';\n\nfunction atRule(mode: ResponsiveMode, maxPx: number): string {\n return mode === 'container'\n ? `@container (max-width: ${maxPx}px)`\n : `@media (max-width: ${maxPx}px)`;\n}\n\n/** N-column field grid that caps at 2 columns on tablet (<=768) and stacks to 1 on phone (<=480). */\nexport function fieldGridStyle(columns: ColumnCount, mode: ResponsiveMode = 'media'): StyleObject {\n const capped = Math.min(columns, 2) as ColumnCount;\n return {\n display: 'grid',\n gridTemplateColumns: gridTemplateForColumns(columns),\n gap: '4px 24px',\n selectors: {\n [atRule(mode, BREAKPOINTS.md)]: { gridTemplateColumns: gridTemplateForColumns(capped) },\n [atRule(mode, BREAKPOINTS.sm)]: { gridTemplateColumns: '1fr' },\n },\n };\n}\n\n/** Multi-section tab row that collapses straight to a single column on tablet (<=768). */\nexport function sectionStackingStyle(gridTemplateColumns: string, mode: ResponsiveMode = 'media'): StyleObject {\n return {\n display: 'grid',\n gridTemplateColumns,\n gap: 16,\n alignItems: 'start',\n selectors: {\n [atRule(mode, BREAKPOINTS.md)]: { gridTemplateColumns: '1fr' },\n },\n };\n}\n\n/** \"Label : input\" row that collapses the label above the input on phone (<=480). */\nexport function fieldRowStyle(labelWidth = '130px', mode: ResponsiveMode = 'media'): StyleObject {\n return {\n display: 'grid',\n gridTemplateColumns: `${labelWidth} 1fr`,\n alignItems: 'center',\n gap: 8,\n minHeight: 38,\n selectors: {\n [atRule(mode, BREAKPOINTS.sm)]: { gridTemplateColumns: '1fr', alignItems: 'flex-start', minHeight: 0, gap: 4 },\n },\n };\n}\n","// Re-exported from @dataverse-kit/design-tokens — the single canonical source of the\n// Dynamics design tokens. surface-kit no longer keeps its own copy (this retires the old\n// \"SYNCED FROM reusable-components\" duplication). The values are pure-TS (no react /\n// no @fluentui), so they remain safe to import from anywhere. `createDynamicsTheme()` and\n// `density` stay here in surface-kit (see ./theme and ./density).\nexport { colors, spacing, typography, radius, layout } from '@dataverse-kit/design-tokens';\n","// Spacing density multiplier — `comfortable` (Dynamics default) vs `compact`\n// (denser forms / embedded PCF). Pure-TS.\nexport type Density = 'comfortable' | 'compact';\n\nexport const densityScale = {\n comfortable: 1,\n compact: 0.75,\n} as const;\n\n/** Scale a base spacing value (px) by the active density. */\nexport function scaleSpacing(value: number, density: Density = 'comfortable'): number {\n return Math.round(value * densityScale[density]);\n}\n","// SYNCED FROM: shared/responsive-patterns/03-layouts/container-query/ContainerQuery.tsx (useContainerSize)\n// Inlined, not aliased: shared/responsive-patterns is outside the npm workspace. The\n// ContainerSize type is inlined here too (rather than vendoring shared/shared/types).\n// This is a React hook, so it lives in hooks/ (NOT responsive/, which must stay\n// framework-agnostic for the ./responsive subpath that export-engine inlines).\nimport * as React from 'react';\nimport { useState, useEffect } from 'react';\n\nexport interface ContainerSize {\n width: number;\n height: number;\n inlineSize: number;\n blockSize: number;\n}\n\n/** Observe an element's size via ResizeObserver. Pass a ref; returns {width,height,inlineSize,blockSize}. */\nexport function useContainerSize<T extends HTMLElement = HTMLElement>(ref: React.RefObject<T>): ContainerSize {\n const [size, setSize] = useState<ContainerSize>({ width: 0, height: 0, inlineSize: 0, blockSize: 0 });\n\n useEffect(() => {\n if (!ref.current || typeof ResizeObserver === 'undefined') return;\n\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height } = entry.contentRect;\n const inlineSize = entry.borderBoxSize?.[0]?.inlineSize ?? width;\n const blockSize = entry.borderBoxSize?.[0]?.blockSize ?? height;\n setSize({ width, height, inlineSize, blockSize });\n }\n });\n\n observer.observe(ref.current);\n return () => observer.disconnect();\n }, [ref]);\n\n return size;\n}\n","import * as React from 'react';\nimport { useRef } from 'react';\nimport { useContainerSize } from './useContainerSize';\n\n/**\n * Create-and-return a ref plus the observed width of the element it is attached to.\n * `const [ref, width] = useContainerWidth(); return <div ref={ref}>…</div>`.\n */\nexport function useContainerWidth<T extends HTMLElement = HTMLDivElement>(): [React.RefObject<T>, number] {\n const ref = useRef<T>(null);\n const { width } = useContainerSize(ref);\n return [ref, width];\n}\n","import type * as React from 'react';\nimport { resolveBreakpoint, type Breakpoint } from '../responsive/breakpoints';\nimport { useContainerWidth } from './useContainerWidth';\n\n/**\n * Resolve the *container's* current breakpoint (not the viewport's) — the correctness\n * fix for a surface inside a PCF, where width comes from `context.allocatedWidth`.\n * Returns `[ref, breakpoint, width]`.\n */\nexport function useContainerBreakpoint<T extends HTMLElement = HTMLDivElement>(): [React.RefObject<T>, Breakpoint, number] {\n const [ref, width] = useContainerWidth<T>();\n return [ref, resolveBreakpoint(width), width];\n}\n","import type * as React from 'react';\nimport { resolveResponsiveValue, type ResponsiveValue } from '../responsive/breakpoints';\nimport { useContainerBreakpoint } from './useContainerBreakpoint';\n\n/**\n * Resolve a responsive value against the *container's* current breakpoint.\n * `const [ref, cols] = useResponsiveValue({ xs: 1, md: 2, lg: 3 });`\n */\nexport function useResponsiveValue<T, E extends HTMLElement = HTMLDivElement>(\n value: ResponsiveValue<T>,\n): [React.RefObject<E>, T | undefined] {\n const [ref, breakpoint] = useContainerBreakpoint<E>();\n return [ref, resolveResponsiveValue(value, breakpoint)];\n}\n","import { useState, useEffect } from 'react';\n\n/** Viewport media-query match — the SSR-safe / no-ResizeObserver fallback to the container hooks. */\nexport function useMediaQuery(query: string): boolean {\n const [matches, setMatches] = useState<boolean>(() => {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return false;\n return window.matchMedia(query).matches;\n });\n\n useEffect(() => {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return;\n const mql = window.matchMedia(query);\n const onChange = () => setMatches(mql.matches);\n onChange();\n mql.addEventListener('change', onChange);\n return () => mql.removeEventListener('change', onChange);\n }, [query]);\n\n return matches;\n}\n","import { createContext, useContext } from 'react';\nimport type { Density } from '../tokens/density';\n\n/**\n * Form-level spacing density. `FormSurface` provides it; `Section` (and any future\n * container) reads it via `useDensity()`, so a single `density` switch on the form\n * cascades to every section instead of being set per-section. Defaults to\n * `'comfortable'` (the Dynamics default) — `'compact'` scales spacing by 0.75.\n */\nexport const DensityContext = createContext<Density>('comfortable');\n\n/** Read the ambient spacing density (defaults to `'comfortable'` outside a provider). */\nexport const useDensity = (): Density => useContext(DensityContext);\n","// A Fluent UI v9 theme for the Dynamics surfaces. The v9 counterpart of the v8\n// `createDynamicsTheme()` (../tokens/theme.ts): where the v8 builder feeds the canonical\n// @dataverse-kit/design-tokens palette into a v8 `createTheme`, this builder feeds the\n// SAME brand triad (brand / brandHover / brandDark) into a v9 `BrandVariants` ramp and\n// `createLightTheme`. So a Dynamics-blue button is #0078d4 from ONE source across both skins.\nimport {\n createLightTheme,\n createDarkTheme,\n type BrandVariants,\n type Theme,\n} from '@fluentui/react-components';\nimport { colors } from '../tokens/tokens';\n\n// The Fluent web brand ramp (a blue family that already matches Dynamics CE), with the\n// three most-visible shades (60 pressed / 70 hover / 80 rest — the ones `createLightTheme`\n// maps to `colorBrandBackground*` and the compound-brand foreground) pinned to the canonical\n// design-tokens brand triad so the v9 brand colors come from the same source as v8's.\nexport const dynamicsBrandRamp: BrandVariants = {\n 10: '#061724',\n 20: '#082338',\n 30: '#0a2e4a',\n 40: '#0c3b5e',\n 50: '#0e4775',\n 60: colors.brandDark, // #005a9e — colorBrandBackgroundPressed\n 70: colors.brandHover, // #106ebe — colorBrandBackground(Hover/Selected)\n 80: colors.brand, // #0078d4 — colorBrandBackground + colorBrandForeground1 (the Dynamics blue)\n 90: '#2886de',\n 100: '#479ef5',\n 110: '#62abf5',\n 120: '#77b7f7',\n 130: '#96c6fa',\n 140: '#b4d6fa',\n 150: '#cfe4fa',\n 160: '#ebf3fc',\n};\n\n/**\n * Build a Fluent v9 `Theme` for the Dynamics surfaces. Defaults to the Dynamics-blue\n * brand ramp; pass a custom `BrandVariants` (e.g. from your org's brand) to override.\n * Wrap the app (or a `./v9` surface subtree) in `<FluentProvider theme={createDynamicsV9Theme()}>`.\n */\nexport function createDynamicsV9Theme(brand: BrandVariants = dynamicsBrandRamp): Theme {\n return createLightTheme(brand);\n}\n\n/** Dark-mode variant of the Dynamics v9 theme (same brand ramp). */\nexport function createDynamicsV9DarkTheme(brand: BrandVariants = dynamicsBrandRamp): Theme {\n return createDarkTheme(brand);\n}\n\n/** The default light Dynamics v9 theme (memoized module singleton). */\nexport const dynamicsV9Theme: Theme = createDynamicsV9Theme();\n","import React from 'react';\nimport { makeStyles, mergeClasses, tokens } from '@fluentui/react-components';\nimport type { FormSurfaceProps } from '../types';\nimport { scaleSpacing } from '../../tokens/density';\nimport { BREAKPOINTS, type Breakpoint } from '../../responsive/breakpoints';\nimport { DensityContext } from '../../hooks/useDensity';\n\n// The Fluent v9 counterpart of the v8 FormSurface: the N-column form canvas that Sections\n// sit on. Same logic — stacks children to full width below `collapseBelow`, driven by the\n// *container* width when `containerWidth` is supplied (PCF allocatedWidth), else by the\n// viewport via @media — re-skinned with griffel (makeStyles) + v9 theme tokens. The\n// density/breakpoint math is the SHARED framework-agnostic layer (scaleSpacing, BREAKPOINTS).\n\nconst useStyles = makeStyles({\n root: {\n display: 'grid',\n alignItems: 'start',\n backgroundColor: tokens.colorNeutralBackground2,\n },\n // Container forced a single column: reset every child's span the same way the @media\n // fallback does, so a Section with `columnStart` doesn't escape the stack.\n forceStackChildren: {\n '& > *': { gridColumn: '1 / -1' },\n },\n // Viewport fallbacks (used only when containerWidth is unset) — one static slot per\n // breakpoint so griffel gets literal media strings. The px come from the shared BREAKPOINTS.\n stackSm: { [`@media (max-width: ${BREAKPOINTS.sm}px)`]: { '& > *': { gridColumn: '1 / -1' } } },\n stackMd: { [`@media (max-width: ${BREAKPOINTS.md}px)`]: { '& > *': { gridColumn: '1 / -1' } } },\n stackLg: { [`@media (max-width: ${BREAKPOINTS.lg}px)`]: { '& > *': { gridColumn: '1 / -1' } } },\n stackXl: { [`@media (max-width: ${BREAKPOINTS.xl}px)`]: { '& > *': { gridColumn: '1 / -1' } } },\n});\n\nconst VIEWPORT_STACK: Record<Breakpoint, keyof ReturnType<typeof useStyles> | null> = {\n xs: null, // xs = 0px, never stacks\n sm: 'stackSm',\n md: 'stackMd',\n lg: 'stackLg',\n xl: 'stackXl',\n};\n\n/** The N-column form canvas that hosts Sections (Fluent UI v9). */\nexport const FormSurface: React.FC<FormSurfaceProps> = ({\n columns = 12,\n gap = 20,\n padding = 20,\n density = 'comfortable',\n background,\n containerWidth,\n collapseBelow = 'sm',\n maxWidth,\n className,\n style,\n children,\n}) => {\n const styles = useStyles();\n const collapsePx = BREAKPOINTS[collapseBelow];\n const forceStack = containerWidth != null && containerWidth <= collapsePx;\n // Density scales the canvas gap + padding; cascades to child Sections via context.\n const scaledGap = scaleSpacing(gap, density);\n const scaledPadding = scaleSpacing(padding, density);\n\n const viewportStackSlot = containerWidth == null ? VIEWPORT_STACK[collapseBelow] : null;\n\n const cls = mergeClasses(\n styles.root,\n forceStack && styles.forceStackChildren,\n viewportStackSlot ? styles[viewportStackSlot] : undefined,\n className,\n );\n\n const inlineStyle: React.CSSProperties = {\n gridTemplateColumns: forceStack ? '1fr' : `repeat(${columns}, 1fr)`,\n gap: scaledGap,\n padding: scaledPadding,\n ...(background != null ? { background } : {}),\n ...(maxWidth != null ? { maxWidth, marginLeft: 'auto', marginRight: 'auto' } : {}),\n ...style,\n };\n\n return (\n <DensityContext.Provider value={density}>\n <div className={cls} style={inlineStyle}>\n {children}\n </div>\n </DensityContext.Provider>\n );\n};\n\nexport default FormSurface;\n","import React from 'react';\nimport type { PageSurfaceProps } from '../types';\nimport { FormSurface } from './FormSurface';\n\n/** A full-page FormSurface (Fluent v9) — optionally centered with a comfortable max width. */\nexport const PageSurface: React.FC<PageSurfaceProps> = ({ centered, maxWidth, ...rest }) => (\n <FormSurface maxWidth={maxWidth ?? (centered ? 1200 : undefined)} {...rest} />\n);\n\nexport default PageSurface;\n","import React, { useState } from 'react';\nimport { makeStyles, mergeClasses, tokens } from '@fluentui/react-components';\nimport type { SectionProps } from '../types';\nimport { scaleSpacing } from '../../tokens/density';\nimport { BREAKPOINTS } from '../../responsive/breakpoints';\nimport { useDensity } from '../../hooks/useDensity';\nimport { SectionHeader } from './SectionHeader';\n\n// The Fluent v9 counterpart of the v8 Section: a grid-positioned card with a header and an\n// internal N-column field grid + the three `variant`s (card/flat/placeholder), `collapsible`,\n// and phone-stacking of the body. Chrome is inline (v9 theme `tokens` are CSS-var strings, so\n// they stay theme-reactive); only the @media child-stacking uses griffel. Density math is the\n// shared framework-agnostic layer (scaleSpacing).\n\nconst useStyles = makeStyles({\n // Phone-stack the internal field grid below `sm` (griffel — inline can't do @media).\n bodyStack: {\n [`@media (max-width: ${BREAKPOINTS.sm}px)`]: { '& > *': { gridColumn: '1 / -1' } },\n },\n});\n\n/** A Dynamics-CE form section (Fluent v9): positioned card with a header and an internal field grid. */\nexport const Section: React.FC<SectionProps> = ({\n title,\n columnSpan = 12,\n columnStart,\n rowPosition,\n internalColumns = 12,\n showCommandBar,\n commandItems,\n statusText,\n notification,\n collapsible,\n defaultCollapsed = false,\n collapsed: controlledCollapsed,\n onCollapsedChange,\n variant = 'card',\n minHeight = 80,\n density: densityProp,\n className,\n style,\n children,\n}) => {\n const styles = useStyles();\n const [internalCollapsed, setInternalCollapsed] = useState(defaultCollapsed);\n const collapsed = controlledCollapsed ?? internalCollapsed;\n const toggle = () => {\n const next = !collapsed;\n if (controlledCollapsed == null) setInternalCollapsed(next);\n onCollapsedChange?.(next);\n };\n\n // Density: an explicit prop wins, else inherit the ambient FormSurface density.\n const ctxDensity = useDensity();\n const density = densityProp ?? ctxDensity;\n const cardPad = `${scaleSpacing(3, density)}px ${scaleSpacing(20, density)}px ${scaleSpacing(20, density)}px ${scaleSpacing(20, density)}px`;\n const bodyGap = scaleSpacing(7, density);\n\n const gridColumn = columnStart ? `${columnStart} / span ${columnSpan}` : `span ${columnSpan}`;\n const rootStyle: React.CSSProperties = {\n gridColumn,\n ...(rowPosition ? { gridRowStart: rowPosition } : {}),\n ...style,\n };\n\n if (variant === 'placeholder') {\n const placeholderStyle: React.CSSProperties = {\n ...rootStyle,\n border: `1px dashed ${tokens.colorNeutralStroke2}`,\n borderRadius: tokens.borderRadiusMedium,\n minHeight,\n width: '100%',\n background: 'transparent',\n };\n return <div className={className} style={placeholderStyle} />;\n }\n\n const chrome: React.CSSProperties =\n variant === 'flat'\n ? {\n backgroundColor: tokens.colorNeutralBackground1,\n borderRadius: tokens.borderRadiusMedium,\n padding: cardPad,\n minWidth: 300,\n width: '100%',\n overflow: 'hidden',\n }\n : {\n backgroundColor: tokens.colorNeutralBackground1,\n border: `1px solid ${tokens.colorNeutralStroke2}`,\n borderRadius: tokens.borderRadiusMedium,\n boxShadow: tokens.shadow4,\n padding: cardPad,\n minWidth: 300,\n width: '100%',\n overflow: 'hidden',\n };\n\n const showHeader = Boolean(title) || showCommandBar || collapsible;\n\n const bodyStyle: React.CSSProperties = {\n display: 'grid',\n gridTemplateColumns: `repeat(${internalColumns}, 1fr)`,\n gap: bodyGap,\n alignItems: 'start',\n };\n\n return (\n <div className={className} style={{ ...chrome, ...rootStyle }}>\n {notification && <div style={{ marginBottom: scaleSpacing(8, density) }}>{notification}</div>}\n {showHeader && (\n <SectionHeader\n title={title}\n statusText={statusText}\n showCommandBar={showCommandBar}\n commandItems={commandItems}\n collapsible={collapsible}\n collapsed={collapsed}\n onToggle={toggle}\n />\n )}\n {!collapsed && (\n <div className={mergeClasses(styles.bodyStack)} style={bodyStyle}>\n {children}\n </div>\n )}\n </div>\n );\n};\n\nexport default Section;\n","import React from 'react';\nimport {\n Button,\n Text,\n Toolbar,\n ToolbarButton,\n tokens,\n} from '@fluentui/react-components';\nimport { ChevronDown20Regular, ChevronRight20Regular } from '@fluentui/react-icons';\nimport type { SectionHeaderProps } from '../types';\n\n// v9 section header: flex title + status on the left, a v9 <Toolbar> of commandItems on the\n// right (replacing the v8 CommandBar), Dynamics neutral underline, optional collapse chevron.\n\n/** Section header bar (Fluent v9): title + status (left), toolbar / actions (right), optional collapse toggle. */\nexport const SectionHeader: React.FC<SectionHeaderProps> = ({\n title,\n statusText,\n showCommandBar,\n commandItems = [],\n actions,\n collapsible,\n collapsed,\n onToggle,\n}) => {\n const rootStyle: React.CSSProperties = {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n flexWrap: 'nowrap',\n borderBottom: `1px solid ${tokens.colorNeutralStroke2}`,\n marginBottom: 16,\n minHeight: 48,\n width: '100%',\n };\n const leftStyle: React.CSSProperties = { display: 'flex', alignItems: 'center', gap: 8, minWidth: 0 };\n const statusStyle: React.CSSProperties = {\n marginLeft: 8,\n fontSize: tokens.fontSizeBase200,\n color: tokens.colorNeutralForeground3,\n };\n\n return (\n <div style={rootStyle}>\n <div style={leftStyle}>\n {collapsible && (\n <Button\n appearance=\"subtle\"\n size=\"small\"\n icon={collapsed ? <ChevronRight20Regular /> : <ChevronDown20Regular />}\n onClick={onToggle}\n aria-label={collapsed ? 'Expand section' : 'Collapse section'}\n aria-expanded={!collapsed}\n />\n )}\n {title && (\n <Text weight=\"semibold\" size={300}>\n {title}\n </Text>\n )}\n {statusText && <span style={statusStyle}>{statusText}</span>}\n </div>\n {actions ? (\n <div>{actions}</div>\n ) : showCommandBar && commandItems.length > 0 ? (\n <Toolbar aria-label=\"Section commands\" size=\"small\">\n {commandItems.map((item) => (\n <ToolbarButton\n key={item.id}\n icon={item.icon}\n appearance={item.appearance === 'primary' ? 'primary' : 'subtle'}\n disabled={item.disabled}\n onClick={item.onClick}\n >\n {item.label}\n </ToolbarButton>\n ))}\n </Toolbar>\n ) : null}\n </div>\n );\n};\n\nexport default SectionHeader;\n","import React from 'react';\nimport { tokens } from '@fluentui/react-components';\nimport type { SectionCardProps } from '../types';\nimport { Section } from './Section';\n\n/**\n * A Section with the Dynamics blue accent top border (Fluent v9).\n * The accent is an inline `borderTop` so it wins over the card variant's inline `border`\n * (see Section: `style` is spread after the card chrome). Defaults to the v9 brand stroke.\n */\nexport const SectionCard: React.FC<SectionCardProps> = ({\n accentColor = tokens.colorBrandStroke1,\n accentWidth = 3,\n variant = 'card',\n style,\n ...rest\n}) => (\n <Section\n variant={variant}\n {...rest}\n style={{ borderTop: `${accentWidth}px solid ${accentColor}`, ...style }}\n />\n);\n\nexport default SectionCard;\n","import React from 'react';\nimport { Text, tokens } from '@fluentui/react-components';\nimport type { FormHeaderProps } from '../types';\n\n/** Dynamics form header (Fluent v9): persona + title/status (left), KPI/header fields (right). */\nexport const FormHeader: React.FC<FormHeaderProps> = ({\n title,\n subtitle,\n status,\n titleColor,\n subtitleColor,\n persona,\n actions,\n className,\n}) => {\n const rootStyle: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 12,\n padding: '12px 24px',\n borderBottom: `1px solid ${tokens.colorNeutralStroke2}`,\n backgroundColor: tokens.colorNeutralBackground1,\n };\n const mainStyle: React.CSSProperties = { display: 'flex', alignItems: 'center', gap: 12, minWidth: 0 };\n const titleRowStyle: React.CSSProperties = { display: 'flex', alignItems: 'baseline', gap: 8, flexWrap: 'wrap' };\n const statusStyle: React.CSSProperties = { fontSize: tokens.fontSizeBase200, color: tokens.colorNeutralForeground3 };\n const subtitleStyle: React.CSSProperties = {\n fontSize: tokens.fontSizeBase200,\n color: subtitleColor || tokens.colorNeutralForeground3,\n marginTop: 2,\n };\n\n return (\n <div className={className} style={rootStyle}>\n <div style={mainStyle}>\n {persona}\n <div>\n <div style={titleRowStyle}>\n {title != null && (\n <Text weight=\"semibold\" size={400} style={titleColor ? { color: titleColor } : undefined}>\n {title}\n </Text>\n )}\n {status != null && <span style={statusStyle}>{status}</span>}\n </div>\n {subtitle != null && <div style={subtitleStyle}>{subtitle}</div>}\n </div>\n </div>\n {actions != null && <div>{actions}</div>}\n </div>\n );\n};\n\nexport default FormHeader;\n","import React, { useState } from 'react';\nimport { TabList, Tab, type SelectTabData, type SelectTabEvent } from '@fluentui/react-components';\nimport type { PivotSurfaceProps } from '../types';\n\n/** Tabbed surface (Fluent v9 `TabList`). Controlled via `selectedId`/`onTabChange` or uncontrolled. */\nexport const PivotSurface: React.FC<PivotSurfaceProps> = ({\n tabs,\n selectedId,\n defaultSelectedId,\n onTabChange,\n appearance = 'transparent',\n size = 'medium',\n className,\n}) => {\n // Seed to the requested default, else the first *enabled* tab (don't open a disabled one).\n const firstEnabledId = tabs.find((t) => !t.disabled)?.id ?? tabs[0]?.id;\n const [internal, setInternal] = useState<string | undefined>(defaultSelectedId ?? firstEnabledId);\n const selected = selectedId ?? internal;\n\n const handleSelect = (_e: SelectTabEvent, data: SelectTabData) => {\n const id = String(data.value);\n if (selectedId == null) setInternal(id);\n onTabChange?.(id);\n };\n\n const active = tabs.find((t) => t.id === selected) ?? tabs[0];\n\n return (\n <div className={className}>\n <TabList selectedValue={selected} onTabSelect={handleSelect} appearance={appearance} size={size}>\n {tabs.map((t) => (\n <Tab key={t.id} value={t.id} icon={t.icon} disabled={t.disabled}>\n {t.label}\n </Tab>\n ))}\n </TabList>\n <div>{active?.content}</div>\n </div>\n );\n};\n\nexport default PivotSurface;\n","import React from 'react';\nimport {\n Toolbar,\n ToolbarButton,\n Menu,\n MenuTrigger,\n MenuPopover,\n MenuList,\n MenuItem,\n} from '@fluentui/react-components';\nimport { MoreHorizontal20Regular } from '@fluentui/react-icons';\nimport type { CommandSurfaceProps, SurfaceToolbarItem } from '../types';\n\nfunction renderToolbarButton(item: SurfaceToolbarItem): React.ReactElement {\n return (\n <ToolbarButton\n key={item.id}\n icon={item.icon}\n appearance={item.appearance === 'primary' ? 'primary' : 'subtle'}\n disabled={item.disabled}\n onClick={item.onClick}\n >\n {item.label}\n </ToolbarButton>\n );\n}\n\n/** A Dynamics-style command bar (Fluent v9 `Toolbar`), with an optional overflow menu + far items. */\nexport const CommandSurface: React.FC<CommandSurfaceProps> = ({\n items,\n overflowItems,\n farItems,\n size = 'small',\n className,\n}) => {\n const hasFar = Boolean(farItems && farItems.length > 0);\n const hasOverflow = Boolean(overflowItems && overflowItems.length > 0);\n\n const hasPrimary = items.length > 0 || hasOverflow;\n\n return (\n <div className={className} style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n {hasPrimary && (\n <Toolbar aria-label=\"Commands\" size={size}>\n {items.map(renderToolbarButton)}\n {hasOverflow && (\n <Menu>\n <MenuTrigger disableButtonEnhancement>\n <ToolbarButton aria-label=\"More commands\" icon={<MoreHorizontal20Regular />} />\n </MenuTrigger>\n <MenuPopover>\n <MenuList>\n {overflowItems!.map((item) => (\n <MenuItem key={item.id} icon={item.icon} disabled={item.disabled} onClick={item.onClick}>\n {item.label}\n </MenuItem>\n ))}\n </MenuList>\n </MenuPopover>\n </Menu>\n )}\n </Toolbar>\n )}\n {hasFar && (\n // marginLeft:auto keeps far items right-aligned whether or not a primary toolbar renders.\n <Toolbar aria-label=\"Secondary commands\" size={size} style={{ marginLeft: 'auto' }}>\n {farItems!.map(renderToolbarButton)}\n </Toolbar>\n )}\n </div>\n );\n};\n\nexport default CommandSurface;\n","import React from 'react';\nimport { Button, tokens } from '@fluentui/react-components';\nimport type { ActionBarProps, SurfaceActionButton } from '../types';\n\nfunction renderButton(b: SurfaceActionButton): React.ReactElement {\n // v9 appearance: primary → primary, subtle → subtle, default → secondary.\n const appearance = b.appearance === 'primary' ? 'primary' : b.appearance === 'subtle' ? 'subtle' : 'secondary';\n return (\n <Button key={b.id} appearance={appearance} icon={b.icon} disabled={b.disabled} onClick={b.onClick}>\n {b.label}\n </Button>\n );\n}\n\n/** A sticky footer bar of action buttons (Fluent v9), with optional left-aligned buttons. */\nexport const ActionBar: React.FC<ActionBarProps> = ({ buttons, alignment = 'right', sticky = true, className }) => {\n const justify = alignment === 'left' ? 'flex-start' : alignment === 'center' ? 'center' : 'flex-end';\n const visible = buttons.filter((b) => !b.hidden);\n const left = visible.filter((b) => b.position === 'left');\n const right = visible.filter((b) => b.position !== 'left');\n\n const rootStyle: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: left.length ? 'space-between' : justify,\n gap: 8,\n padding: '12px 24px',\n borderTop: `1px solid ${tokens.colorNeutralStroke2}`,\n backgroundColor: tokens.colorNeutralBackground1,\n ...(sticky ? { position: 'sticky', bottom: 0, zIndex: 1 } : {}),\n };\n\n return (\n <div className={className} style={rootStyle}>\n {left.length > 0 && <div style={{ display: 'flex', gap: 8 }}>{left.map(renderButton)}</div>}\n <div style={{ display: 'flex', gap: 8, justifyContent: justify }}>{right.map(renderButton)}</div>\n </div>\n );\n};\n\nexport default ActionBar;\n","import React from 'react';\nimport { tokens } from '@fluentui/react-components';\nimport type { FooterProps } from '../types';\n\n/** A sticky footer region (free-form children, Fluent v9) — e.g. for dialog/panel actions. */\nexport const Footer: React.FC<FooterProps> = ({ sticky = true, align = 'right', className, children }) => {\n const justify = align === 'left' ? 'flex-start' : align === 'center' ? 'center' : 'flex-end';\n const rootStyle: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: justify,\n gap: 8,\n padding: '12px 24px',\n borderTop: `1px solid ${tokens.colorNeutralStroke2}`,\n backgroundColor: tokens.colorNeutralBackground1,\n ...(sticky ? { position: 'sticky', bottom: 0, zIndex: 1 } : {}),\n };\n return (\n <div className={className} style={rootStyle}>\n {children}\n </div>\n );\n};\n\nexport default Footer;\n","import React from 'react';\nimport { Dialog, DialogSurface, Button, Text, tokens } from '@fluentui/react-components';\nimport { Dismiss20Regular } from '@fluentui/react-icons';\nimport type { FormDialogSurfaceProps } from '../types';\nimport { dialogWidthCss, dialogHeightCss } from '../../core/sizePresets';\n\n// The Fluent v9 counterpart of the v8 FormDialogSurface (a `<Modal>`): a controlled\n// `<Dialog>` + `<DialogSurface>` sized from the SHARED sizing scalars (dialogWidthCss /\n// dialogHeightCss — the same 1200 / 95vh contract the v8 skin and the codegen use), with a\n// custom header (title/subheader | counter + close), a scrolling content region, and a\n// sticky footer. Content is rendered directly in DialogSurface (padding managed here) so the\n// flex-column scroll layout matches the v8 Modal main/scrollableContent.\n\n/**\n * Full Dynamics form-dialog (Fluent v9 `Dialog`). Default width 1200 (lg), height 95vh.\n * `onDismiss` is the close affordance — when omitted, no close button renders. `isBlocking`\n * maps to the dialog `modalType` (`modal` vs `non-modal`).\n */\nexport const FormDialogSurface: React.FC<FormDialogSurfaceProps> = ({\n isOpen,\n onDismiss,\n title,\n subheader,\n size,\n width,\n height,\n isBlocking = true,\n recordCounter,\n footer,\n className,\n children,\n}) => {\n const widthCss = dialogWidthCss({ width, size });\n const heightCss = dialogHeightCss(height);\n const showHeader = Boolean(title) || Boolean(recordCounter) || Boolean(onDismiss);\n\n const headerStyle: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 12,\n padding: '12px 20px',\n borderBottom: `1px solid ${tokens.colorNeutralStroke2}`,\n };\n const counterStyle: React.CSSProperties = { fontSize: tokens.fontSizeBase200, color: tokens.colorNeutralForeground3 };\n\n return (\n <Dialog\n open={isOpen}\n modalType={isBlocking ? 'modal' : 'non-modal'}\n onOpenChange={(_e, data) => {\n if (!data.open) onDismiss?.();\n }}\n >\n <DialogSurface\n className={className}\n style={{\n maxWidth: '95vw',\n width: widthCss,\n height: heightCss,\n maxHeight: '95vh',\n display: 'flex',\n flexDirection: 'column',\n padding: 0,\n }}\n >\n {showHeader && (\n <div style={headerStyle}>\n <div style={{ display: 'flex', flexDirection: 'column', minWidth: 0 }}>\n {title && (\n <Text weight=\"semibold\" size={400}>\n {title}\n </Text>\n )}\n {subheader && (\n <span style={{ fontSize: tokens.fontSizeBase200, color: tokens.colorNeutralForeground3, marginTop: 2 }}>\n {subheader}\n </span>\n )}\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n {recordCounter && (\n <span style={counterStyle}>\n {recordCounter.current} of {recordCounter.total}\n </span>\n )}\n {onDismiss && (\n <Button appearance=\"subtle\" aria-label=\"Close\" icon={<Dismiss20Regular />} onClick={onDismiss} />\n )}\n </div>\n </div>\n )}\n <div style={{ flex: 1, minHeight: 0, overflow: 'auto', padding: 20 }}>{children}</div>\n {footer && (\n <div style={{ borderTop: `1px solid ${tokens.colorNeutralStroke2}`, padding: '12px 20px' }}>{footer}</div>\n )}\n </DialogSurface>\n </Dialog>\n );\n};\n\nexport default FormDialogSurface;\n","import React from 'react';\nimport { Dialog, DialogSurface, Text, tokens } from '@fluentui/react-components';\nimport type { ModalSurfaceProps } from '../types';\nimport { dialogWidthPx, MODAL_AUTOSIZE_MIN_WIDTH } from '../../core/sizePresets';\n\n/** A generic modal (Fluent v9 `Dialog`) — title + content + optional footer; lighter than FormDialogSurface. */\nexport const ModalSurface: React.FC<ModalSurfaceProps> = ({\n isOpen,\n onDismiss,\n title,\n size,\n width,\n isBlocking = true,\n autoSize,\n footer,\n className,\n children,\n}) => {\n const sizing: React.CSSProperties = autoSize\n ? { width: 'auto', minWidth: MODAL_AUTOSIZE_MIN_WIDTH, maxWidth: '100%' }\n : { maxWidth: '95vw', width: `${dialogWidthPx({ width, size })}px` };\n\n return (\n <Dialog\n open={isOpen}\n modalType={isBlocking ? 'modal' : 'non-modal'}\n onOpenChange={(_e, data) => {\n if (!data.open) onDismiss?.();\n }}\n >\n <DialogSurface className={className} style={{ ...sizing, padding: 0 }}>\n {title && (\n <div style={{ padding: '16px 20px 0' }}>\n <Text weight=\"semibold\" size={500}>\n {title}\n </Text>\n </div>\n )}\n <div style={{ padding: 20 }}>{children}</div>\n {footer && (\n <div\n style={{\n borderTop: `1px solid ${tokens.colorNeutralStroke2}`,\n padding: '12px 20px',\n display: 'flex',\n justifyContent: 'flex-end',\n gap: 8,\n }}\n >\n {footer}\n </div>\n )}\n </DialogSurface>\n </Dialog>\n );\n};\n\nexport default ModalSurface;\n","import React from 'react';\nimport {\n OverlayDrawer,\n DrawerHeader,\n DrawerHeaderTitle,\n DrawerBody,\n Button,\n} from '@fluentui/react-components';\nimport { Dismiss24Regular } from '@fluentui/react-icons';\nimport type { PanelSurfaceProps } from '../types';\n\n// The Fluent v9 counterpart of the v8 PanelSurface (a `<Panel>`): a right-edge\n// `<OverlayDrawer>`. The v8 medium-vs-custom width heuristic (>500 → medium) maps to the\n// v9 Drawer `size`; an explicit `width` renders a custom-width drawer. `isLightDismiss`\n// controls backdrop-click dismissal (Esc still closes); `isNonModal` drops the blocking overlay.\n\n/** A Dynamics side panel (Fluent v9 `OverlayDrawer`). */\nexport const PanelSurface: React.FC<PanelSurfaceProps> = ({\n isOpen,\n onDismiss,\n title,\n drawerSize,\n width,\n hasCloseButton = true,\n isLightDismiss = true,\n isNonModal = false,\n footer,\n children,\n}) => {\n const size = drawerSize ?? (width != null && width > 500 ? 'medium' : 'small');\n const customWidthStyle = width != null ? ({ width: `${width}px` } as React.CSSProperties) : undefined;\n\n return (\n <OverlayDrawer\n open={isOpen}\n position=\"end\"\n size={size}\n modalType={isNonModal ? 'non-modal' : 'modal'}\n style={customWidthStyle}\n onOpenChange={(_e, data) => {\n if (data.open) return;\n // Honor isLightDismiss for backdrop clicks; Esc + explicit close always dismiss.\n if (data.type === 'backdropClick' && !isLightDismiss) return;\n onDismiss?.();\n }}\n >\n <DrawerHeader>\n <DrawerHeaderTitle\n action={\n hasCloseButton && onDismiss ? (\n <Button appearance=\"subtle\" aria-label=\"Close\" icon={<Dismiss24Regular />} onClick={onDismiss} />\n ) : undefined\n }\n >\n {title}\n </DrawerHeaderTitle>\n </DrawerHeader>\n <DrawerBody>\n <div style={{ padding: '12px 0' }}>{children}</div>\n {footer && <div style={{ marginTop: 'auto', paddingTop: 12 }}>{footer}</div>}\n </DrawerBody>\n </OverlayDrawer>\n );\n};\n\nexport default PanelSurface;\n","import React from 'react';\nimport { Popover, PopoverSurface, type PositioningShorthand } from '@fluentui/react-components';\nimport type { CalloutSurfaceProps } from '../types';\nimport { calloutWidthPx } from '../../core/sizePresets';\n\n// The Fluent v9 counterpart of the v8 CalloutSurface (a `<Callout>`): a controlled,\n// target-anchored `<Popover>` + `<PopoverSurface>`. v8's `target` (selector / element / ref)\n// is resolved to an element and passed via `positioning.target`; there is no PopoverTrigger\n// because anchoring comes from the target (matching the v8 target-based API). `isBeakVisible`\n// maps to `withArrow`.\n\nfunction resolveTarget(target: CalloutSurfaceProps['target']): HTMLElement | null {\n if (!target) return null;\n if (typeof target === 'string') return document.querySelector<HTMLElement>(target);\n if ('current' in target) return (target.current as HTMLElement | null) ?? null;\n return target as HTMLElement;\n}\n\n/** A lightweight contextual callout (Fluent v9 `Popover`) anchored to a target. */\nexport const CalloutSurface: React.FC<CalloutSurfaceProps> = ({\n target,\n isOpen = true,\n onDismiss,\n width,\n position = 'below',\n align = 'start',\n isBeakVisible = true,\n className,\n children,\n}) => {\n if (!isOpen) return null;\n const el = resolveTarget(target);\n // If the target can't be resolved (selector miss / target={null}), the Popover renders\n // unanchored (position defaults apply) rather than throwing — an intentional soft fallback.\n const positioning: PositioningShorthand = { position, align, ...(el ? { target: el } : {}) };\n\n return (\n <Popover\n open\n trapFocus={false}\n withArrow={isBeakVisible}\n positioning={positioning}\n onOpenChange={(_e, data) => {\n if (!data.open) onDismiss?.();\n }}\n >\n <PopoverSurface className={className} style={{ width: calloutWidthPx(width), padding: 16 }}>\n {children}\n </PopoverSurface>\n </Popover>\n );\n};\n\nexport default CalloutSurface;\n","import React from 'react';\nimport { Tooltip } from '@fluentui/react-components';\nimport type { TooltipSurfaceProps } from '../types';\n\nconst DELAY_MS: Record<NonNullable<TooltipSurfaceProps['delay']>, number> = {\n zero: 0,\n medium: 250,\n long: 500,\n};\n\n/** A tooltip wrapper (Fluent v9 `Tooltip`). */\nexport const TooltipSurface: React.FC<TooltipSurfaceProps> = ({\n content,\n position = 'above',\n delay = 'medium',\n relationship = 'label',\n children,\n}) => (\n <Tooltip content={content} relationship={relationship} positioning={position} showDelay={DELAY_MS[delay]}>\n {children}\n </Tooltip>\n);\n\nexport default TooltipSurface;\n"],"mappings":"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","names":["useState","useEffect","jsx","useState","makeStyles","mergeClasses","tokens","tokens","jsx","jsx","jsxs","useStyles","makeStyles","useState","tokens","mergeClasses","tokens","jsx","tokens","Text","tokens","jsx","jsxs","useState","jsx","jsxs","Toolbar","ToolbarButton","jsx","jsxs","Button","tokens","jsx","jsxs","tokens","jsx","Button","Text","tokens","jsx","jsxs","tokens","Text","Button","Dialog","DialogSurface","Text","tokens","jsx","jsxs","Dialog","DialogSurface","Text","tokens","Button","jsx","jsxs","jsx","jsx"]}
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@dataverse-kit/surface-kit",
3
- "version": "0.2.0",
4
- "description": "Shared, responsive surfaces / containers / layouts for Dynamics 365 (Fluent UI v8). Form shells, sections, tabs, and overlay surfaces (Dialog/Modal/Panel/Callout/Tooltip) that match Dynamics CE and host grid-kit grids. The pure-TS ./core (sizing) and ./responsive (breakpoint builders) subpaths are framework-agnostic and shared with the export-engine codegen.",
3
+ "version": "0.3.0",
4
+ "license": "MIT",
5
+ "description": "Shared, responsive surfaces / containers / layouts for Dynamics 365. Form shells, sections, tabs, and overlay surfaces (Dialog/Modal/Panel/Callout/Tooltip) that match Dynamics CE and host grid-kit grids, in both Fluent UI v8 (the default `.` entry) and Fluent UI v9 (the `./v9` entry). The pure-TS ./core (sizing) and ./responsive (breakpoint builders) subpaths are framework-agnostic and shared by both skins and the export-engine codegen.",
5
6
  "type": "module",
6
7
  "main": "./dist/index.cjs",
7
8
  "module": "./dist/index.mjs",
@@ -21,6 +22,11 @@
21
22
  "types": "./dist/responsive.d.ts",
22
23
  "import": "./dist/responsive.mjs",
23
24
  "require": "./dist/responsive.cjs"
25
+ },
26
+ "./v9": {
27
+ "types": "./dist/v9.d.ts",
28
+ "import": "./dist/v9.mjs",
29
+ "require": "./dist/v9.cjs"
24
30
  }
25
31
  },
26
32
  "files": [
@@ -45,15 +51,27 @@
45
51
  "clean": "rimraf dist coverage tsconfig.tsbuildinfo storybook-static"
46
52
  },
47
53
  "dependencies": {
48
- "@dataverse-kit/design-tokens": "^0.1.0"
54
+ "@dataverse-kit/design-tokens": "^0.1.1"
49
55
  },
50
56
  "peerDependencies": {
51
57
  "@fluentui/react": "^8.115.6",
58
+ "@fluentui/react-components": "^9.46.2",
59
+ "@fluentui/react-icons": "^2.0.239",
52
60
  "react": "^18.2.0",
53
61
  "react-dom": "^18.2.0"
54
62
  },
63
+ "peerDependenciesMeta": {
64
+ "@fluentui/react-components": {
65
+ "optional": true
66
+ },
67
+ "@fluentui/react-icons": {
68
+ "optional": true
69
+ }
70
+ },
55
71
  "devDependencies": {
56
72
  "@fluentui/react": "^8.115.6",
73
+ "@fluentui/react-components": "^9.46.2",
74
+ "@fluentui/react-icons": "^2.0.239",
57
75
  "@storybook/addon-docs": "^10.4.4",
58
76
  "@storybook/react-vite": "^10.4.4",
59
77
  "@testing-library/react": "^14.0.0",