flexily 0.5.1 → 0.6.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.
- package/README.md +1 -1
- package/dist/chunk-CBBoxR_p.mjs +26 -0
- package/dist/constants-BNURa6H7.mjs +65 -0
- package/dist/constants-BNURa6H7.mjs.map +1 -0
- package/dist/constants-D7ythAJC.d.mts +64 -0
- package/dist/constants-D7ythAJC.d.mts.map +1 -0
- package/{src/classic/node.ts → dist/index-classic.d.mts} +118 -619
- package/dist/index-classic.d.mts.map +1 -0
- package/dist/index-classic.mjs +1909 -0
- package/dist/index-classic.mjs.map +1 -0
- package/dist/index.d.mts +195 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +3279 -0
- package/dist/index.mjs.map +1 -0
- package/dist/node-zero-75maLs2s.d.mts +762 -0
- package/dist/node-zero-75maLs2s.d.mts.map +1 -0
- package/dist/src-BWyhokNZ.mjs +692 -0
- package/dist/src-BWyhokNZ.mjs.map +1 -0
- package/dist/src-DdSLylRA.mjs +816 -0
- package/dist/src-DdSLylRA.mjs.map +1 -0
- package/dist/testing.d.mts +55 -0
- package/dist/testing.d.mts.map +1 -0
- package/dist/testing.mjs +154 -0
- package/dist/testing.mjs.map +1 -0
- package/dist/types--IozHd4V.mjs +283 -0
- package/dist/types--IozHd4V.mjs.map +1 -0
- package/dist/types-DG1H4DVR.d.mts +157 -0
- package/dist/types-DG1H4DVR.d.mts.map +1 -0
- package/package.json +34 -24
- package/src/CLAUDE.md +0 -527
- package/src/classic/layout.ts +0 -1843
- package/src/constants.ts +0 -82
- package/src/create-flexily.ts +0 -153
- package/src/index-classic.ts +0 -110
- package/src/index.ts +0 -133
- package/src/layout-flex-lines.ts +0 -413
- package/src/layout-helpers.ts +0 -160
- package/src/layout-measure.ts +0 -259
- package/src/layout-stats.ts +0 -41
- package/src/layout-traversal.ts +0 -70
- package/src/layout-zero.ts +0 -2219
- package/src/logger.ts +0 -67
- package/src/monospace-measurer.ts +0 -68
- package/src/node-zero.ts +0 -1508
- package/src/pretext-measurer.ts +0 -86
- package/src/test-measurer.ts +0 -219
- package/src/testing.ts +0 -215
- package/src/text-layout.ts +0 -75
- package/src/trace.ts +0 -252
- package/src/types.ts +0 -236
- package/src/utils.ts +0 -243
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types--IozHd4V.mjs","names":[],"sources":["../src/utils.ts","../src/logger.ts","../src/types.ts"],"sourcesContent":["/**\n * Flexily Utility Functions\n *\n * Helper functions for edge value manipulation and value resolution.\n */\n\nimport * as C from \"./constants.js\"\nimport type { Value } from \"./types.js\"\n\n// ============================================================================\n// Shared Traversal Stack\n// ============================================================================\n// Pre-allocated stack array for iterative tree traversal. Shared across all\n// layout functions to avoid multiple allocations. Using a single stack is safe\n// because layout operations are synchronous (no concurrent traversals).\n\n/**\n * Shared traversal stack for iterative tree operations.\n * Avoids recursion (prevents stack overflow on deep trees) and avoids\n * allocation during layout passes.\n */\nexport const traversalStack: unknown[] = []\n\n/**\n * Set a value on an edge array (supports all edge types including logical START/END).\n */\nexport function setEdgeValue(\n arr: [Value, Value, Value, Value, Value, Value],\n edge: number,\n value: number,\n unit: number,\n): void {\n const v = { value, unit }\n switch (edge) {\n case C.EDGE_LEFT:\n arr[0] = v\n break\n case C.EDGE_TOP:\n arr[1] = v\n break\n case C.EDGE_RIGHT:\n arr[2] = v\n break\n case C.EDGE_BOTTOM:\n arr[3] = v\n break\n case C.EDGE_HORIZONTAL:\n arr[0] = v\n arr[2] = v\n break\n case C.EDGE_VERTICAL:\n arr[1] = v\n arr[3] = v\n break\n case C.EDGE_ALL:\n arr[0] = v\n arr[1] = v\n arr[2] = v\n arr[3] = v\n break\n case C.EDGE_START:\n // Store in logical START slot (resolved to physical at layout time)\n arr[4] = v\n break\n case C.EDGE_END:\n // Store in logical END slot (resolved to physical at layout time)\n arr[5] = v\n break\n }\n}\n\n/**\n * Set a border value on an edge array.\n */\nexport function setEdgeBorder(\n arr: [number, number, number, number, number, number],\n edge: number,\n value: number,\n): void {\n switch (edge) {\n case C.EDGE_LEFT:\n arr[0] = value\n break\n case C.EDGE_TOP:\n arr[1] = value\n break\n case C.EDGE_RIGHT:\n arr[2] = value\n break\n case C.EDGE_BOTTOM:\n arr[3] = value\n break\n case C.EDGE_HORIZONTAL:\n arr[0] = value\n arr[2] = value\n break\n case C.EDGE_VERTICAL:\n arr[1] = value\n arr[3] = value\n break\n case C.EDGE_ALL:\n arr[0] = value\n arr[1] = value\n arr[2] = value\n arr[3] = value\n break\n case C.EDGE_START:\n // Store in logical START slot (resolved to physical at layout time)\n arr[4] = value\n break\n case C.EDGE_END:\n // Store in logical END slot (resolved to physical at layout time)\n arr[5] = value\n break\n }\n}\n\n/**\n * Get a value from an edge array.\n */\nexport function getEdgeValue(arr: [Value, Value, Value, Value, Value, Value], edge: number): Value {\n switch (edge) {\n case C.EDGE_LEFT:\n return arr[0]\n case C.EDGE_TOP:\n return arr[1]\n case C.EDGE_RIGHT:\n return arr[2]\n case C.EDGE_BOTTOM:\n return arr[3]\n case C.EDGE_START:\n return arr[4]\n case C.EDGE_END:\n return arr[5]\n default:\n return arr[0] // Default to left\n }\n}\n\n/**\n * Get a border value from an edge array.\n */\nexport function getEdgeBorderValue(arr: [number, number, number, number, number, number], edge: number): number {\n switch (edge) {\n case C.EDGE_LEFT:\n return arr[0]\n case C.EDGE_TOP:\n return arr[1]\n case C.EDGE_RIGHT:\n return arr[2]\n case C.EDGE_BOTTOM:\n return arr[3]\n case C.EDGE_START:\n return arr[4]\n case C.EDGE_END:\n return arr[5]\n default:\n return arr[0] // Default to left\n }\n}\n\n/**\n * Resolve a value (point or percent) to an absolute number.\n */\nexport function resolveValue(value: Value, availableSize: number): number {\n switch (value.unit) {\n case C.UNIT_POINT:\n return value.value\n case C.UNIT_PERCENT:\n // Percentage against NaN (auto-sized parent) resolves to 0\n if (Number.isNaN(availableSize)) {\n return 0\n }\n return availableSize * (value.value / 100)\n default:\n return 0\n }\n}\n\n/**\n * Apply min/max constraints to a size.\n *\n * CSS behavior:\n * - min: Floor constraint. Does NOT affect children's layout — the container expands\n * after shrink-wrap. When size is NaN (auto-sized), min is NOT applied here;\n * the post-shrink-wrap applyMinMax call (Phase 9) handles it.\n * - max: Ceiling constraint. DOES affect children's layout — content wraps/clips\n * within the max. When size is NaN (auto-sized), max constrains the container\n * so children are laid out within the max bound.\n *\n * Percent constraints that can't resolve (available is NaN) are skipped entirely,\n * since resolveValue returns 0 for percent-against-NaN, which would incorrectly\n * clamp sizes to 0.\n */\nexport function applyMinMax(size: number, min: Value, max: Value, available: number): number {\n let result = size\n\n // Apply max first, then min. CSS spec: when min > max, min wins.\n // By applying max before min, Math.max(result, minValue) ensures min dominates.\n\n if (max.unit !== C.UNIT_UNDEFINED) {\n // Skip percent max when available is NaN — can't resolve meaningfully\n if (max.unit === C.UNIT_PERCENT && Number.isNaN(available)) {\n // Skip: percent against NaN resolves to 0, which would be wrong\n } else {\n const maxValue = resolveValue(max, available)\n if (!Number.isNaN(maxValue)) {\n // Apply max as ceiling even when size is NaN (auto-sized).\n // This constrains children's layout to the max bound.\n // Phase 9 shrink-wrap may reduce it further; the post-shrink-wrap\n // applyMinMax call ensures max is still respected.\n if (Number.isNaN(result)) {\n // For auto-sized nodes, only apply finite max constraints.\n // Infinity means \"no real constraint\" (e.g., silvery sets\n // maxWidth=Infinity as default) and should not replace NaN.\n if (maxValue !== Infinity) {\n result = maxValue\n }\n } else {\n result = Math.min(result, maxValue)\n }\n }\n }\n }\n\n if (min.unit !== C.UNIT_UNDEFINED) {\n // Skip percent min when available is NaN — can't resolve meaningfully\n if (min.unit === C.UNIT_PERCENT && Number.isNaN(available)) {\n // Skip: percent against NaN resolves to 0, which would be wrong\n } else {\n const minValue = resolveValue(min, available)\n if (!Number.isNaN(minValue)) {\n // Only apply min to definite sizes. When size is NaN (auto-sized),\n // skip — the post-shrink-wrap applyMinMax call will floor it.\n if (!Number.isNaN(result)) {\n result = Math.max(result, minValue)\n }\n }\n }\n }\n\n return result\n}\n","/**\n * Logger with auto-detection\n *\n * Uses @beorn/logger if available (when used in km), falls back to debug library.\n * Supports the conditional `?.` pattern for zero-cost when disabled.\n */\n\n// Debug library style: (msg, ...args) - printf-style formatting\ntype DebugFn = (msg: string, ...args: unknown[]) => void\n\ninterface ConditionalLogger {\n debug?: DebugFn\n}\n\nlet _logger: ConditionalLogger | null = null\n\nasync function createFallbackLogger(namespace: string): Promise<ConditionalLogger> {\n // Dynamic import to avoid bundling debug if not needed\n try {\n const { default: createDebug } = (await import(\"debug\")) as {\n default: (ns: string) => DebugFn & { enabled: boolean }\n }\n const debug = createDebug(namespace)\n return { debug: debug.enabled ? debug : undefined }\n } catch {\n // debug not installed either\n return { debug: undefined }\n }\n}\n\nasync function detectLogger(namespace: string): Promise<ConditionalLogger> {\n try {\n const { createLogger } = await import(\"loggily\")\n const logger = createLogger(namespace)\n // Wrap @beorn/logger to accept printf-style args\n if (logger.debug) {\n const originalDebug = logger.debug\n return {\n debug: (msg: string, ...args: unknown[]) => {\n // Format printf-style placeholders\n let i = 0\n const formatted = msg.replace(/%[sdOo]/g, () => {\n const arg = args[i++]\n if (arg === undefined) return \"\"\n if (arg === null) return \"null\"\n if (typeof arg === \"object\") return JSON.stringify(arg)\n return String(arg)\n })\n originalDebug(formatted)\n },\n }\n }\n return { debug: undefined }\n } catch {\n return createFallbackLogger(namespace)\n }\n}\n\n// Eagerly initialize (top-level await)\n// This runs once at module load time\n_logger = await detectLogger(\"flexily:layout\")\n\n/** Logger instance - use with optional chaining: `log.debug?.('message')` */\nexport const log: ConditionalLogger = {\n get debug() {\n return _logger?.debug\n },\n}\n","/**\n * Flexily Types\n *\n * TypeScript interfaces for the flexbox layout engine.\n */\n\n/**\n * A value with a unit (point, percent, or auto).\n */\nexport interface Value {\n value: number\n unit: number // UNIT_UNDEFINED | UNIT_POINT | UNIT_PERCENT | UNIT_AUTO\n}\n\n/**\n * Measure function signature for intrinsic sizing.\n * Called by the layout algorithm to determine a node's natural size.\n */\nexport type MeasureFunc = (\n width: number,\n widthMode: number,\n height: number,\n heightMode: number,\n) => { width: number; height: number }\n\n/**\n * Baseline function signature for baseline alignment.\n * Called by the layout algorithm to determine a node's baseline offset from its top edge.\n * Used with ALIGN_BASELINE to align text baselines across siblings.\n *\n * @param width - The computed width of the node\n * @param height - The computed height of the node\n * @returns The baseline offset from the top of the node (in points)\n */\nexport type BaselineFunc = (width: number, height: number) => number\n\n/**\n * Cache entry for measure results.\n * Stores input constraints (w, wm, h, hm) and output (rw, rh).\n */\nexport interface MeasureEntry {\n w: number\n wm: number\n h: number\n hm: number\n rw: number\n rh: number\n}\n\n/**\n * Cache entry for layout results.\n * Stores input available dimensions and computed size.\n * Used to avoid redundant recursive layout calls during a single pass.\n */\nexport interface LayoutCacheEntry {\n availW: number // Available width (may be NaN)\n availH: number // Available height (may be NaN)\n computedW: number // Computed width\n computedH: number // Computed height\n}\n\n/**\n * Per-node flex calculation state for zero-allocation layout.\n *\n * This interface enables the layout engine to avoid heap allocations during\n * layout passes by storing all intermediate calculation state directly on\n * each Node. Fields are mutated (not recreated) each pass.\n *\n * Design rationale:\n * - Eliminates ChildLayout object allocation (previously created per child per pass)\n * - Enables filtered iteration via relativeIndex (avoids temporary array allocation)\n * - Stores line membership for flex-wrap (avoids FlexLine[] allocation)\n *\n * All numeric fields use number (Float64 in V8) for precision. Boolean fields\n * track state that affects the CSS Flexbox algorithm's iterative distribution.\n *\n * @see layout.ts for usage in layoutNode() and distributeFlexSpaceForLine()\n */\nexport interface FlexInfo {\n /** Computed main-axis size after flex distribution */\n mainSize: number\n /** Original base size before flex distribution (used for weighted shrink) */\n baseSize: number\n /** Total main-axis margin (non-auto margins only) */\n mainMargin: number\n /** flex-grow factor from style */\n flexGrow: number\n /** flex-shrink factor from style */\n flexShrink: number\n /** Resolved min-width/height constraint on main axis */\n minMain: number\n /** Resolved max-width/height constraint on main axis (Infinity if none) */\n maxMain: number\n /** Whether main-start margin is auto (absorbs free space) */\n mainStartMarginAuto: boolean\n /** Whether main-end margin is auto (absorbs free space) */\n mainEndMarginAuto: boolean\n /** Resolved main-start margin value (0 if auto, computed later) */\n mainStartMarginValue: number\n /** Resolved main-end margin value (0 if auto, computed later) */\n mainEndMarginValue: number\n /** Cached resolved margin values [left, top, right, bottom] */\n marginL: number\n marginT: number\n marginR: number\n marginB: number\n /** Frozen in flex distribution (clamped to min/max constraint) */\n frozen: boolean\n /** Line index for flex-wrap (0-based, which line this child belongs to) */\n lineIndex: number\n /**\n * Relative index for filtered iteration.\n * -1 = absolute positioned or display:none (skip in flex layout)\n * 0+ = index among relative children (participates in flex layout)\n */\n relativeIndex: number\n /** Computed baseline offset for ALIGN_BASELINE (zero-alloc: avoids per-pass array) */\n baseline: number\n\n // Constraint fingerprinting for layout caching\n /** Last availableWidth passed to layoutNode */\n lastAvailW: number\n /** Last availableHeight passed to layoutNode */\n lastAvailH: number\n /** Last offsetX passed to layoutNode */\n lastOffsetX: number\n /** Last offsetY passed to layoutNode */\n lastOffsetY: number\n /** Last absX passed to layoutNode (affects edge-based rounding) */\n lastAbsX: number\n /** Last absY passed to layoutNode (affects edge-based rounding) */\n lastAbsY: number\n /** Whether cached layout is valid (fingerprint matched, not dirty) */\n layoutValid: boolean\n /** Last direction passed to layoutNode */\n lastDir: number\n}\n\n/**\n * Computed layout result for a node.\n */\nexport interface Layout {\n left: number\n top: number\n width: number\n height: number\n}\n\n/**\n * Internal style properties for a node.\n */\nexport interface Style {\n // Display\n display: number\n\n // Position\n positionType: number\n position: [Value, Value, Value, Value, Value, Value] // [left, top, right, bottom, start, end]\n\n // Flex\n flexDirection: number\n flexWrap: number\n flexGrow: number\n flexShrink: number\n flexBasis: Value\n\n // Alignment\n alignItems: number\n alignSelf: number\n alignContent: number\n justifyContent: number\n\n // Size\n width: Value\n height: Value\n minWidth: Value\n minHeight: Value\n maxWidth: Value\n maxHeight: Value\n aspectRatio: number // NaN = undefined, otherwise width/height ratio\n\n // Spacing (per-edge: left, top, right, bottom, start, end)\n // Physical edges: [0]=left, [1]=top, [2]=right, [3]=bottom\n // Logical edges: [4]=start, [5]=end (resolved based on flex direction)\n margin: [Value, Value, Value, Value, Value, Value]\n padding: [Value, Value, Value, Value, Value, Value]\n border: [number, number, number, number, number, number] // Border widths (always points, [4,5] = logical start/end)\n\n // Gap\n gap: [number, number] // [column, row]\n\n // Overflow\n overflow: number\n}\n\n/**\n * Create a default Value (undefined).\n */\nexport function createValue(value = 0, unit = 0): Value {\n return { value, unit }\n}\n\n/**\n * Create default style.\n *\n * Comments indicate where Yoga and CSS defaults differ.\n * Flexily follows Yoga defaults for API compatibility.\n */\nexport function createDefaultStyle(): Style {\n return {\n display: 0, // DISPLAY_FLEX (same in CSS and Yoga)\n positionType: 1, // POSITION_TYPE_RELATIVE (same in CSS and Yoga)\n position: [createValue(), createValue(), createValue(), createValue(), createValue(), createValue()],\n flexDirection: 2, // FLEX_DIRECTION_ROW — CSS default; Yoga defaults to COLUMN\n flexWrap: 0, // WRAP_NO_WRAP (same in CSS and Yoga)\n flexGrow: 0, // (same in CSS and Yoga)\n flexShrink: 0, // Yoga default; CSS defaults to 1\n flexBasis: createValue(0, 3), // AUTO (same in CSS and Yoga)\n alignItems: 4, // ALIGN_STRETCH (same in CSS and Yoga)\n alignSelf: 0, // ALIGN_AUTO (same in CSS and Yoga)\n alignContent: 1, // ALIGN_FLEX_START — Yoga default; CSS defaults to STRETCH\n justifyContent: 0, // JUSTIFY_FLEX_START (same in CSS and Yoga)\n width: createValue(0, 3), // AUTO (same in CSS and Yoga)\n height: createValue(0, 3), // AUTO (same in CSS and Yoga)\n minWidth: createValue(),\n minHeight: createValue(),\n maxWidth: createValue(),\n maxHeight: createValue(),\n aspectRatio: NaN, // undefined by default (same in CSS and Yoga)\n margin: [createValue(), createValue(), createValue(), createValue(), createValue(), createValue()],\n padding: [createValue(), createValue(), createValue(), createValue(), createValue(), createValue()],\n border: [0, 0, 0, 0, NaN, NaN],\n gap: [0, 0],\n overflow: 0, // OVERFLOW_VISIBLE (same in CSS and Yoga)\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAqBA,MAAa,iBAA4B,EAAE;;;;AAK3C,SAAgB,aACd,KACA,MACA,OACA,MACM;CACN,MAAM,IAAI;EAAE;EAAO;EAAM;AACzB,SAAQ,MAAR;EACE,KAAK;AACH,OAAI,KAAK;AACT;EACF,KAAK;AACH,OAAI,KAAK;AACT;EACF,KAAK;AACH,OAAI,KAAK;AACT;EACF,KAAK;AACH,OAAI,KAAK;AACT;EACF,KAAK;AACH,OAAI,KAAK;AACT,OAAI,KAAK;AACT;EACF,KAAK;AACH,OAAI,KAAK;AACT,OAAI,KAAK;AACT;EACF,KAAK;AACH,OAAI,KAAK;AACT,OAAI,KAAK;AACT,OAAI,KAAK;AACT,OAAI,KAAK;AACT;EACF,KAAK;AAEH,OAAI,KAAK;AACT;EACF,KAAK;AAEH,OAAI,KAAK;AACT;;;;;;AAON,SAAgB,cACd,KACA,MACA,OACM;AACN,SAAQ,MAAR;EACE,KAAK;AACH,OAAI,KAAK;AACT;EACF,KAAK;AACH,OAAI,KAAK;AACT;EACF,KAAK;AACH,OAAI,KAAK;AACT;EACF,KAAK;AACH,OAAI,KAAK;AACT;EACF,KAAK;AACH,OAAI,KAAK;AACT,OAAI,KAAK;AACT;EACF,KAAK;AACH,OAAI,KAAK;AACT,OAAI,KAAK;AACT;EACF,KAAK;AACH,OAAI,KAAK;AACT,OAAI,KAAK;AACT,OAAI,KAAK;AACT,OAAI,KAAK;AACT;EACF,KAAK;AAEH,OAAI,KAAK;AACT;EACF,KAAK;AAEH,OAAI,KAAK;AACT;;;;;;AAON,SAAgB,aAAa,KAAiD,MAAqB;AACjG,SAAQ,MAAR;EACE,KAAK,EACH,QAAO,IAAI;EACb,KAAK,EACH,QAAO,IAAI;EACb,KAAK,EACH,QAAO,IAAI;EACb,KAAK,EACH,QAAO,IAAI;EACb,KAAK,EACH,QAAO,IAAI;EACb,KAAK,EACH,QAAO,IAAI;EACb,QACE,QAAO,IAAI;;;;;;AAOjB,SAAgB,mBAAmB,KAAuD,MAAsB;AAC9G,SAAQ,MAAR;EACE,KAAK,EACH,QAAO,IAAI;EACb,KAAK,EACH,QAAO,IAAI;EACb,KAAK,EACH,QAAO,IAAI;EACb,KAAK,EACH,QAAO,IAAI;EACb,KAAK,EACH,QAAO,IAAI;EACb,KAAK,EACH,QAAO,IAAI;EACb,QACE,QAAO,IAAI;;;;;;AAOjB,SAAgB,aAAa,OAAc,eAA+B;AACxE,SAAQ,MAAM,MAAd;EACE,KAAK,EACH,QAAO,MAAM;EACf,KAAK;AAEH,OAAI,OAAO,MAAM,cAAc,CAC7B,QAAO;AAET,UAAO,iBAAiB,MAAM,QAAQ;EACxC,QACE,QAAO;;;;;;;;;;;;;;;;;;AAmBb,SAAgB,YAAY,MAAc,KAAY,KAAY,WAA2B;CAC3F,IAAI,SAAS;AAKb,KAAI,IAAI,SAAS,EAEf,KAAI,IAAI,SAAS,KAAkB,OAAO,MAAM,UAAU,EAAE,QAErD;EACL,MAAM,WAAW,aAAa,KAAK,UAAU;AAC7C,MAAI,CAAC,OAAO,MAAM,SAAS,CAKzB,KAAI,OAAO,MAAM,OAAO;OAIlB,aAAa,SACf,UAAS;QAGX,UAAS,KAAK,IAAI,QAAQ,SAAS;;AAM3C,KAAI,IAAI,SAAS,EAEf,KAAI,IAAI,SAAS,KAAkB,OAAO,MAAM,UAAU,EAAE,QAErD;EACL,MAAM,WAAW,aAAa,KAAK,UAAU;AAC7C,MAAI,CAAC,OAAO,MAAM,SAAS;OAGrB,CAAC,OAAO,MAAM,OAAO,CACvB,UAAS,KAAK,IAAI,QAAQ,SAAS;;;AAM3C,QAAO;;;;ACnOT,IAAI,UAAoC;AAExC,eAAe,qBAAqB,WAA+C;AAEjF,KAAI;EACF,MAAM,EAAE,SAAS,gBAAiB,MAAM,OAAO,sBAAA,MAAA,MAAA,wBAAA,EAAA,SAAA,EAAA,CAAA;EAG/C,MAAM,QAAQ,YAAY,UAAU;AACpC,SAAO,EAAE,OAAO,MAAM,UAAU,QAAQ,KAAA,GAAW;SAC7C;AAEN,SAAO,EAAE,OAAO,KAAA,GAAW;;;AAI/B,eAAe,aAAa,WAA+C;AACzE,KAAI;EACF,MAAM,EAAE,iBAAiB,MAAM,OAAO;EACtC,MAAM,SAAS,aAAa,UAAU;AAEtC,MAAI,OAAO,OAAO;GAChB,MAAM,gBAAgB,OAAO;AAC7B,UAAO,EACL,QAAQ,KAAa,GAAG,SAAoB;IAE1C,IAAI,IAAI;AAQR,kBAPkB,IAAI,QAAQ,kBAAkB;KAC9C,MAAM,MAAM,KAAK;AACjB,SAAI,QAAQ,KAAA,EAAW,QAAO;AAC9B,SAAI,QAAQ,KAAM,QAAO;AACzB,SAAI,OAAO,QAAQ,SAAU,QAAO,KAAK,UAAU,IAAI;AACvD,YAAO,OAAO,IAAI;MAClB,CACsB;MAE3B;;AAEH,SAAO,EAAE,OAAO,KAAA,GAAW;SACrB;AACN,SAAO,qBAAqB,UAAU;;;AAM1C,UAAU,MAAM,aAAa,iBAAiB;;AAG9C,MAAa,MAAyB,EACpC,IAAI,QAAQ;AACV,QAAO,SAAS;GAEnB;;;;;;ACmID,SAAgB,YAAY,QAAQ,GAAG,OAAO,GAAU;AACtD,QAAO;EAAE;EAAO;EAAM;;;;;;;;AASxB,SAAgB,qBAA4B;AAC1C,QAAO;EACL,SAAS;EACT,cAAc;EACd,UAAU;GAAC,aAAa;GAAE,aAAa;GAAE,aAAa;GAAE,aAAa;GAAE,aAAa;GAAE,aAAa;GAAC;EACpG,eAAe;EACf,UAAU;EACV,UAAU;EACV,YAAY;EACZ,WAAW,YAAY,GAAG,EAAE;EAC5B,YAAY;EACZ,WAAW;EACX,cAAc;EACd,gBAAgB;EAChB,OAAO,YAAY,GAAG,EAAE;EACxB,QAAQ,YAAY,GAAG,EAAE;EACzB,UAAU,aAAa;EACvB,WAAW,aAAa;EACxB,UAAU,aAAa;EACvB,WAAW,aAAa;EACxB,aAAa;EACb,QAAQ;GAAC,aAAa;GAAE,aAAa;GAAE,aAAa;GAAE,aAAa;GAAE,aAAa;GAAE,aAAa;GAAC;EAClG,SAAS;GAAC,aAAa;GAAE,aAAa;GAAE,aAAa;GAAE,aAAa;GAAE,aAAa;GAAE,aAAa;GAAC;EACnG,QAAQ;GAAC;GAAG;GAAG;GAAG;GAAG;GAAK;GAAI;EAC9B,KAAK,CAAC,GAAG,EAAE;EACX,UAAU;EACX"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Flexily Types
|
|
4
|
+
*
|
|
5
|
+
* TypeScript interfaces for the flexbox layout engine.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* A value with a unit (point, percent, or auto).
|
|
9
|
+
*/
|
|
10
|
+
interface Value {
|
|
11
|
+
value: number;
|
|
12
|
+
unit: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Measure function signature for intrinsic sizing.
|
|
16
|
+
* Called by the layout algorithm to determine a node's natural size.
|
|
17
|
+
*/
|
|
18
|
+
type MeasureFunc = (width: number, widthMode: number, height: number, heightMode: number) => {
|
|
19
|
+
width: number;
|
|
20
|
+
height: number;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Baseline function signature for baseline alignment.
|
|
24
|
+
* Called by the layout algorithm to determine a node's baseline offset from its top edge.
|
|
25
|
+
* Used with ALIGN_BASELINE to align text baselines across siblings.
|
|
26
|
+
*
|
|
27
|
+
* @param width - The computed width of the node
|
|
28
|
+
* @param height - The computed height of the node
|
|
29
|
+
* @returns The baseline offset from the top of the node (in points)
|
|
30
|
+
*/
|
|
31
|
+
type BaselineFunc = (width: number, height: number) => number;
|
|
32
|
+
/**
|
|
33
|
+
* Per-node flex calculation state for zero-allocation layout.
|
|
34
|
+
*
|
|
35
|
+
* This interface enables the layout engine to avoid heap allocations during
|
|
36
|
+
* layout passes by storing all intermediate calculation state directly on
|
|
37
|
+
* each Node. Fields are mutated (not recreated) each pass.
|
|
38
|
+
*
|
|
39
|
+
* Design rationale:
|
|
40
|
+
* - Eliminates ChildLayout object allocation (previously created per child per pass)
|
|
41
|
+
* - Enables filtered iteration via relativeIndex (avoids temporary array allocation)
|
|
42
|
+
* - Stores line membership for flex-wrap (avoids FlexLine[] allocation)
|
|
43
|
+
*
|
|
44
|
+
* All numeric fields use number (Float64 in V8) for precision. Boolean fields
|
|
45
|
+
* track state that affects the CSS Flexbox algorithm's iterative distribution.
|
|
46
|
+
*
|
|
47
|
+
* @see layout.ts for usage in layoutNode() and distributeFlexSpaceForLine()
|
|
48
|
+
*/
|
|
49
|
+
interface FlexInfo {
|
|
50
|
+
/** Computed main-axis size after flex distribution */
|
|
51
|
+
mainSize: number;
|
|
52
|
+
/** Original base size before flex distribution (used for weighted shrink) */
|
|
53
|
+
baseSize: number;
|
|
54
|
+
/** Total main-axis margin (non-auto margins only) */
|
|
55
|
+
mainMargin: number;
|
|
56
|
+
/** flex-grow factor from style */
|
|
57
|
+
flexGrow: number;
|
|
58
|
+
/** flex-shrink factor from style */
|
|
59
|
+
flexShrink: number;
|
|
60
|
+
/** Resolved min-width/height constraint on main axis */
|
|
61
|
+
minMain: number;
|
|
62
|
+
/** Resolved max-width/height constraint on main axis (Infinity if none) */
|
|
63
|
+
maxMain: number;
|
|
64
|
+
/** Whether main-start margin is auto (absorbs free space) */
|
|
65
|
+
mainStartMarginAuto: boolean;
|
|
66
|
+
/** Whether main-end margin is auto (absorbs free space) */
|
|
67
|
+
mainEndMarginAuto: boolean;
|
|
68
|
+
/** Resolved main-start margin value (0 if auto, computed later) */
|
|
69
|
+
mainStartMarginValue: number;
|
|
70
|
+
/** Resolved main-end margin value (0 if auto, computed later) */
|
|
71
|
+
mainEndMarginValue: number;
|
|
72
|
+
/** Cached resolved margin values [left, top, right, bottom] */
|
|
73
|
+
marginL: number;
|
|
74
|
+
marginT: number;
|
|
75
|
+
marginR: number;
|
|
76
|
+
marginB: number;
|
|
77
|
+
/** Frozen in flex distribution (clamped to min/max constraint) */
|
|
78
|
+
frozen: boolean;
|
|
79
|
+
/** Line index for flex-wrap (0-based, which line this child belongs to) */
|
|
80
|
+
lineIndex: number;
|
|
81
|
+
/**
|
|
82
|
+
* Relative index for filtered iteration.
|
|
83
|
+
* -1 = absolute positioned or display:none (skip in flex layout)
|
|
84
|
+
* 0+ = index among relative children (participates in flex layout)
|
|
85
|
+
*/
|
|
86
|
+
relativeIndex: number;
|
|
87
|
+
/** Computed baseline offset for ALIGN_BASELINE (zero-alloc: avoids per-pass array) */
|
|
88
|
+
baseline: number;
|
|
89
|
+
/** Last availableWidth passed to layoutNode */
|
|
90
|
+
lastAvailW: number;
|
|
91
|
+
/** Last availableHeight passed to layoutNode */
|
|
92
|
+
lastAvailH: number;
|
|
93
|
+
/** Last offsetX passed to layoutNode */
|
|
94
|
+
lastOffsetX: number;
|
|
95
|
+
/** Last offsetY passed to layoutNode */
|
|
96
|
+
lastOffsetY: number;
|
|
97
|
+
/** Last absX passed to layoutNode (affects edge-based rounding) */
|
|
98
|
+
lastAbsX: number;
|
|
99
|
+
/** Last absY passed to layoutNode (affects edge-based rounding) */
|
|
100
|
+
lastAbsY: number;
|
|
101
|
+
/** Whether cached layout is valid (fingerprint matched, not dirty) */
|
|
102
|
+
layoutValid: boolean;
|
|
103
|
+
/** Last direction passed to layoutNode */
|
|
104
|
+
lastDir: number;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Computed layout result for a node.
|
|
108
|
+
*/
|
|
109
|
+
interface Layout {
|
|
110
|
+
left: number;
|
|
111
|
+
top: number;
|
|
112
|
+
width: number;
|
|
113
|
+
height: number;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Internal style properties for a node.
|
|
117
|
+
*/
|
|
118
|
+
interface Style {
|
|
119
|
+
display: number;
|
|
120
|
+
positionType: number;
|
|
121
|
+
position: [Value, Value, Value, Value, Value, Value];
|
|
122
|
+
flexDirection: number;
|
|
123
|
+
flexWrap: number;
|
|
124
|
+
flexGrow: number;
|
|
125
|
+
flexShrink: number;
|
|
126
|
+
flexBasis: Value;
|
|
127
|
+
alignItems: number;
|
|
128
|
+
alignSelf: number;
|
|
129
|
+
alignContent: number;
|
|
130
|
+
justifyContent: number;
|
|
131
|
+
width: Value;
|
|
132
|
+
height: Value;
|
|
133
|
+
minWidth: Value;
|
|
134
|
+
minHeight: Value;
|
|
135
|
+
maxWidth: Value;
|
|
136
|
+
maxHeight: Value;
|
|
137
|
+
aspectRatio: number;
|
|
138
|
+
margin: [Value, Value, Value, Value, Value, Value];
|
|
139
|
+
padding: [Value, Value, Value, Value, Value, Value];
|
|
140
|
+
border: [number, number, number, number, number, number];
|
|
141
|
+
gap: [number, number];
|
|
142
|
+
overflow: number;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Create a default Value (undefined).
|
|
146
|
+
*/
|
|
147
|
+
declare function createValue(value?: number, unit?: number): Value;
|
|
148
|
+
/**
|
|
149
|
+
* Create default style.
|
|
150
|
+
*
|
|
151
|
+
* Comments indicate where Yoga and CSS defaults differ.
|
|
152
|
+
* Flexily follows Yoga defaults for API compatibility.
|
|
153
|
+
*/
|
|
154
|
+
declare function createDefaultStyle(): Style;
|
|
155
|
+
//#endregion
|
|
156
|
+
export { Style as a, createValue as c, MeasureFunc as i, FlexInfo as n, Value as o, Layout as r, createDefaultStyle as s, BaselineFunc as t };
|
|
157
|
+
//# sourceMappingURL=types-DG1H4DVR.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-DG1H4DVR.d.mts","names":[],"sources":["../src/types.ts"],"mappings":";;AASA;;;;;AASA;;UATiB,KAAA;EACf,KAAA;EACA,IAAA;AAAA;;;;;KAOU,WAAA,IACV,KAAA,UACA,SAAA,UACA,MAAA,UACA,UAAA;EACK,KAAA;EAAe,MAAA;AAAA;;;;AAuDtB;;;;;;KA5CY,YAAA,IAAgB,KAAA,UAAe,MAAA;;;;AA2G3C;;;;;;;;;;AAUA;;;;UAzEiB,QAAA;EA+EU;EA7EzB,QAAA;EA6EuC;EA3EvC,QAAA;EAkFW;EAhFX,UAAA;EA0FQ;EAxFR,QAAA;EA0FW;EAxFX,UAAA;EA0FW;EAxFX,OAAA;EA8FgB;EA5FhB,OAAA;EA4F8B;EA1F9B,mBAAA;EA0F4C;EAxF5C,iBAAA;EAyFiB;EAvFjB,oBAAA;EAuF+B;EArF/B,kBAAA;EAqF6C;EAnF7C,OAAA;EACA,OAAA;EACA,OAAA;EACA,OAAA;EAoDA;EAlDA,MAAA;EAkDkB;EAhDlB,SAAA;EAgDgC;;;;;EA1ChC,aAAA;EAgDA;EA9CA,QAAA;EA+CW;EA3CX,UAAA;EA+CA;EA7CA,UAAA;EA+CA;EA7CA,WAAA;EAgDO;EA9CP,WAAA;EA+CQ;EA7CR,QAAA;EA8CU;EA5CV,QAAA;EA6CW;EA3CX,WAAA;EA4CU;EA1CV,OAAA;AAAA;;;;UAMe,MAAA;EACf,IAAA;EACA,GAAA;EACA,KAAA;EACA,MAAA;AAAA;;;;UAMe,KAAA;EAEf,OAAA;EAGA,YAAA;EACA,QAAA,GAAW,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA;EAG9C,aAAA;EACA,QAAA;EACA,QAAA;EACA,UAAA;EACA,SAAA,EAAW,KAAA;EAGX,UAAA;EACA,SAAA;EACA,YAAA;EACA,cAAA;EAGA,KAAA,EAAO,KAAA;EACP,MAAA,EAAQ,KAAA;EACR,QAAA,EAAU,KAAA;EACV,SAAA,EAAW,KAAA;EACX,QAAA,EAAU,KAAA;EACV,SAAA,EAAW,KAAA;EACX,WAAA;EAKA,MAAA,GAAS,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA;EAC5C,OAAA,GAAU,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA;EAC7C,MAAA;EAGA,GAAA;EAGA,QAAA;AAAA;;;;iBAMc,WAAA,CAAY,KAAA,WAAW,IAAA,YAAW,KAAA;;;;;;;iBAUlC,kBAAA,CAAA,GAAsB,KAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flexily",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Pure JavaScript flexbox layout engine — composable plugins, text measurement, Yoga-compatible API, no WASM",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"canvas-ui",
|
|
@@ -22,48 +22,36 @@
|
|
|
22
22
|
"url": "https://github.com/beorn/flexily/issues"
|
|
23
23
|
},
|
|
24
24
|
"license": "MIT",
|
|
25
|
-
"author": "
|
|
25
|
+
"author": "Bjørn Stabell <bjorn@stabell.org>",
|
|
26
26
|
"repository": {
|
|
27
27
|
"type": "git",
|
|
28
28
|
"url": "https://github.com/beorn/flexily.git"
|
|
29
29
|
},
|
|
30
30
|
"files": [
|
|
31
|
-
"
|
|
31
|
+
"dist"
|
|
32
32
|
],
|
|
33
33
|
"type": "module",
|
|
34
|
-
"main": "./src/index.ts",
|
|
35
|
-
"types": "./src/index.ts",
|
|
36
34
|
"exports": {
|
|
37
35
|
".": {
|
|
38
|
-
"types": "./
|
|
39
|
-
"import": "./
|
|
36
|
+
"types": "./dist/index.d.mts",
|
|
37
|
+
"import": "./dist/index.mjs"
|
|
40
38
|
},
|
|
41
39
|
"./classic": {
|
|
42
|
-
"types": "./
|
|
43
|
-
"import": "./
|
|
40
|
+
"types": "./dist/index-classic.d.mts",
|
|
41
|
+
"import": "./dist/index-classic.mjs"
|
|
44
42
|
},
|
|
45
43
|
"./testing": {
|
|
46
|
-
"types": "./
|
|
47
|
-
"import": "./
|
|
44
|
+
"types": "./dist/testing.d.mts",
|
|
45
|
+
"import": "./dist/testing.mjs"
|
|
48
46
|
}
|
|
49
47
|
},
|
|
50
48
|
"publishConfig": {
|
|
51
49
|
"access": "public"
|
|
52
50
|
},
|
|
53
|
-
"scripts": {
|
|
54
|
-
"build": "tsc",
|
|
55
|
-
"test": "bun test",
|
|
56
|
-
"test:watch": "bun test --watch",
|
|
57
|
-
"bench": "bunx --bun vitest bench",
|
|
58
|
-
"typecheck": "tsc --noEmit",
|
|
59
|
-
"ci": "bun run typecheck && bun test",
|
|
60
|
-
"docs:dev": "vitepress dev docs",
|
|
61
|
-
"docs:build": "vitepress build docs",
|
|
62
|
-
"docs:preview": "vitepress preview docs"
|
|
63
|
-
},
|
|
64
51
|
"devDependencies": {
|
|
65
52
|
"@types/node": "^25.5.0",
|
|
66
53
|
"loggily": "^0.4.2",
|
|
54
|
+
"tsdown": "^0.21.7",
|
|
67
55
|
"typescript": "^5.9.3",
|
|
68
56
|
"vitepress": "^1.6.3",
|
|
69
57
|
"vitepress-enrich": "^0.4.0",
|
|
@@ -71,7 +59,29 @@
|
|
|
71
59
|
"vitest": "^3.1.0",
|
|
72
60
|
"yoga-wasm-web": "^0.3.3"
|
|
73
61
|
},
|
|
62
|
+
"tsdown": {
|
|
63
|
+
"clean": true,
|
|
64
|
+
"dts": true,
|
|
65
|
+
"entry": [
|
|
66
|
+
"src/index.ts",
|
|
67
|
+
"src/index-classic.ts",
|
|
68
|
+
"src/testing.ts"
|
|
69
|
+
],
|
|
70
|
+
"format": "esm"
|
|
71
|
+
},
|
|
74
72
|
"engines": {
|
|
75
|
-
"
|
|
73
|
+
"bun": ">=1.0",
|
|
74
|
+
"node": ">=18.0.0"
|
|
75
|
+
},
|
|
76
|
+
"scripts": {
|
|
77
|
+
"build": "tsdown",
|
|
78
|
+
"test": "bun test",
|
|
79
|
+
"test:watch": "bun test --watch",
|
|
80
|
+
"bench": "bunx --bun vitest bench",
|
|
81
|
+
"typecheck": "tsc --noEmit",
|
|
82
|
+
"ci": "bun run typecheck && bun test",
|
|
83
|
+
"docs:dev": "vitepress dev docs",
|
|
84
|
+
"docs:build": "vitepress build docs",
|
|
85
|
+
"docs:preview": "vitepress preview docs"
|
|
76
86
|
}
|
|
77
|
-
}
|
|
87
|
+
}
|