@bendyline/squisq 1.2.2 → 1.4.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/dist/{Doc-BfBhiCNr.d.ts → Doc-BeSeH2iX.d.ts} +141 -33
- package/dist/ImageEditDoc-BTIvw0oq.d.ts +84 -0
- package/dist/__tests__/colorUtils.test.d.ts +2 -0
- package/dist/__tests__/colorUtils.test.d.ts.map +1 -0
- package/dist/__tests__/colorUtils.test.js +94 -0
- package/dist/__tests__/colorUtils.test.js.map +1 -0
- package/dist/__tests__/getLayers.test.js +31 -7
- package/dist/__tests__/getLayers.test.js.map +1 -1
- package/dist/__tests__/iconResolve.test.d.ts +2 -0
- package/dist/__tests__/iconResolve.test.d.ts.map +1 -0
- package/dist/__tests__/iconResolve.test.js +99 -0
- package/dist/__tests__/iconResolve.test.js.map +1 -0
- package/dist/__tests__/imageEditState.test.d.ts +2 -0
- package/dist/__tests__/imageEditState.test.d.ts.map +1 -0
- package/dist/__tests__/imageEditState.test.js +61 -0
- package/dist/__tests__/imageEditState.test.js.map +1 -0
- package/dist/__tests__/imageEditVersions.test.d.ts +2 -0
- package/dist/__tests__/imageEditVersions.test.d.ts.map +1 -0
- package/dist/__tests__/imageEditVersions.test.js +141 -0
- package/dist/__tests__/imageEditVersions.test.js.map +1 -0
- package/dist/__tests__/inferDocumentTitle.test.d.ts +2 -0
- package/dist/__tests__/inferDocumentTitle.test.d.ts.map +1 -0
- package/dist/__tests__/inferDocumentTitle.test.js +42 -0
- package/dist/__tests__/inferDocumentTitle.test.js.map +1 -0
- package/dist/__tests__/jsonForm.chooseControl.test.d.ts +2 -0
- package/dist/__tests__/jsonForm.chooseControl.test.d.ts.map +1 -0
- package/dist/__tests__/jsonForm.chooseControl.test.js +74 -0
- package/dist/__tests__/jsonForm.chooseControl.test.js.map +1 -0
- package/dist/__tests__/jsonForm.evaluateWhen.test.d.ts +2 -0
- package/dist/__tests__/jsonForm.evaluateWhen.test.d.ts.map +1 -0
- package/dist/__tests__/jsonForm.evaluateWhen.test.js +51 -0
- package/dist/__tests__/jsonForm.evaluateWhen.test.js.map +1 -0
- package/dist/__tests__/jsonForm.inferSchema.test.d.ts +2 -0
- package/dist/__tests__/jsonForm.inferSchema.test.d.ts.map +1 -0
- package/dist/__tests__/jsonForm.inferSchema.test.js +23 -0
- package/dist/__tests__/jsonForm.inferSchema.test.js.map +1 -0
- package/dist/__tests__/jsonForm.pointer.test.d.ts +2 -0
- package/dist/__tests__/jsonForm.pointer.test.d.ts.map +1 -0
- package/dist/__tests__/jsonForm.pointer.test.js +94 -0
- package/dist/__tests__/jsonForm.pointer.test.js.map +1 -0
- package/dist/__tests__/markdown.test.js +40 -0
- package/dist/__tests__/markdown.test.js.map +1 -1
- package/dist/__tests__/markdownIcons.test.d.ts +2 -0
- package/dist/__tests__/markdownIcons.test.d.ts.map +1 -0
- package/dist/__tests__/markdownIcons.test.js +93 -0
- package/dist/__tests__/markdownIcons.test.js.map +1 -0
- package/dist/__tests__/markdownToDoc.test.js +15 -4
- package/dist/__tests__/markdownToDoc.test.js.map +1 -1
- package/dist/__tests__/recommendTemplates.test.d.ts +2 -0
- package/dist/__tests__/recommendTemplates.test.d.ts.map +1 -0
- package/dist/__tests__/recommendTemplates.test.js +158 -0
- package/dist/__tests__/recommendTemplates.test.js.map +1 -0
- package/dist/__tests__/scopedContentContainer.test.d.ts +2 -0
- package/dist/__tests__/scopedContentContainer.test.d.ts.map +1 -0
- package/dist/__tests__/scopedContentContainer.test.js +74 -0
- package/dist/__tests__/scopedContentContainer.test.js.map +1 -0
- package/dist/__tests__/slideshowGenerator.test.js +1 -1
- package/dist/__tests__/slideshowGenerator.test.js.map +1 -1
- package/dist/__tests__/surface.test.d.ts +2 -0
- package/dist/__tests__/surface.test.d.ts.map +1 -0
- package/dist/__tests__/surface.test.js +57 -0
- package/dist/__tests__/surface.test.js.map +1 -0
- package/dist/__tests__/templateAnnotationParse.test.d.ts +2 -0
- package/dist/__tests__/templateAnnotationParse.test.d.ts.map +1 -0
- package/dist/__tests__/templateAnnotationParse.test.js +42 -0
- package/dist/__tests__/templateAnnotationParse.test.js.map +1 -0
- package/dist/__tests__/templates.test.js +90 -9
- package/dist/__tests__/templates.test.js.map +1 -1
- package/dist/__tests__/themeCompile.test.d.ts +2 -0
- package/dist/__tests__/themeCompile.test.d.ts.map +1 -0
- package/dist/__tests__/themeCompile.test.js +134 -0
- package/dist/__tests__/themeCompile.test.js.map +1 -0
- package/dist/__tests__/themeValidator.test.d.ts +2 -0
- package/dist/__tests__/themeValidator.test.d.ts.map +1 -0
- package/dist/__tests__/themeValidator.test.js +107 -0
- package/dist/__tests__/themeValidator.test.js.map +1 -0
- package/dist/__tests__/versions.test.d.ts +2 -0
- package/dist/__tests__/versions.test.d.ts.map +1 -0
- package/dist/__tests__/versions.test.js +339 -0
- package/dist/__tests__/versions.test.js.map +1 -0
- package/dist/{chunk-CYQHG27J.js → chunk-2TMAWB4Y.js} +74 -1
- package/dist/chunk-2TMAWB4Y.js.map +1 -0
- package/dist/{chunk-LAZELBON.js → chunk-3K5OG6KI.js} +165 -17
- package/dist/chunk-3K5OG6KI.js.map +1 -0
- package/dist/chunk-57CVQCFX.js +193 -0
- package/dist/chunk-57CVQCFX.js.map +1 -0
- package/dist/{chunk-QM5PKNPW.js → chunk-5WFRKURX.js} +1 -1
- package/dist/chunk-5WFRKURX.js.map +1 -0
- package/dist/chunk-B4EEON3N.js +1317 -0
- package/dist/chunk-B4EEON3N.js.map +1 -0
- package/dist/chunk-DBS6RIFL.js +81 -0
- package/dist/chunk-DBS6RIFL.js.map +1 -0
- package/dist/{chunk-MIBRIRGJ.js → chunk-FR2RBTKO.js} +3 -3
- package/dist/{chunk-MIBRIRGJ.js.map → chunk-FR2RBTKO.js.map} +1 -1
- package/dist/chunk-H3AXU4MJ.js +179 -0
- package/dist/chunk-H3AXU4MJ.js.map +1 -0
- package/dist/chunk-JELIRVDP.js +24 -0
- package/dist/chunk-JELIRVDP.js.map +1 -0
- package/dist/chunk-K32VJONL.js +193 -0
- package/dist/chunk-K32VJONL.js.map +1 -0
- package/dist/{chunk-GAQLMORN.js → chunk-KSWJR66U.js} +248 -44
- package/dist/chunk-KSWJR66U.js.map +1 -0
- package/dist/{chunk-TSG2OSE6.js → chunk-MYIH7FWD.js} +3 -3
- package/dist/chunk-MYIH7FWD.js.map +1 -0
- package/dist/chunk-VLJJHDAC.js +218 -0
- package/dist/chunk-VLJJHDAC.js.map +1 -0
- package/dist/chunk-WMOI7FN3.js +182 -0
- package/dist/chunk-WMOI7FN3.js.map +1 -0
- package/dist/chunk-ZTX4PFFT.js +520 -0
- package/dist/chunk-ZTX4PFFT.js.map +1 -0
- package/dist/doc/audioMapping.d.ts.map +1 -1
- package/dist/doc/audioMapping.js +80 -9
- package/dist/doc/audioMapping.js.map +1 -1
- package/dist/doc/getLayers.d.ts.map +1 -1
- package/dist/doc/getLayers.js +29 -18
- package/dist/doc/getLayers.js.map +1 -1
- package/dist/doc/markdownToDoc.d.ts.map +1 -1
- package/dist/doc/markdownToDoc.js +40 -6
- package/dist/doc/markdownToDoc.js.map +1 -1
- package/dist/doc/templates/featureBlock.d.ts +18 -0
- package/dist/doc/templates/featureBlock.d.ts.map +1 -0
- package/dist/doc/templates/featureBlock.js +180 -0
- package/dist/doc/templates/featureBlock.js.map +1 -0
- package/dist/doc/templates/fullBleedQuote.d.ts +12 -0
- package/dist/doc/templates/fullBleedQuote.d.ts.map +1 -1
- package/dist/doc/templates/fullBleedQuote.js +12 -0
- package/dist/doc/templates/fullBleedQuote.js.map +1 -1
- package/dist/doc/templates/index.d.ts +28 -4
- package/dist/doc/templates/index.d.ts.map +1 -1
- package/dist/doc/templates/index.js +45 -12
- package/dist/doc/templates/index.js.map +1 -1
- package/dist/doc/templates/listBlock.d.ts.map +1 -1
- package/dist/doc/templates/listBlock.js +22 -5
- package/dist/doc/templates/listBlock.js.map +1 -1
- package/dist/doc/templates/statHighlight.d.ts +12 -0
- package/dist/doc/templates/statHighlight.d.ts.map +1 -1
- package/dist/doc/templates/statHighlight.js +12 -0
- package/dist/doc/templates/statHighlight.js.map +1 -1
- package/dist/doc/templates/titleBlock.d.ts +11 -0
- package/dist/doc/templates/titleBlock.d.ts.map +1 -1
- package/dist/doc/templates/titleBlock.js +8 -0
- package/dist/doc/templates/titleBlock.js.map +1 -1
- package/dist/doc/utils/themeUtils.d.ts +4 -4
- package/dist/doc/utils/themeUtils.d.ts.map +1 -1
- package/dist/doc/utils/themeUtils.js +8 -7
- package/dist/doc/utils/themeUtils.js.map +1 -1
- package/dist/generate/slideshowGenerator.js +1 -1
- package/dist/generate/slideshowGenerator.js.map +1 -1
- package/dist/generate/templateMapper.js +2 -2
- package/dist/generate/templateMapper.js.map +1 -1
- package/dist/icons/iconData.d.ts +26 -0
- package/dist/icons/iconData.d.ts.map +1 -0
- package/dist/icons/iconData.js +12 -0
- package/dist/icons/iconData.js.map +1 -0
- package/dist/icons/index.d.ts +12 -0
- package/dist/icons/index.d.ts.map +1 -0
- package/dist/icons/index.js +10 -0
- package/dist/icons/index.js.map +1 -0
- package/dist/icons/resolve.d.ts +61 -0
- package/dist/icons/resolve.d.ts.map +1 -0
- package/dist/icons/resolve.js +130 -0
- package/dist/icons/resolve.js.map +1 -0
- package/dist/imageEdit/ImageEditVersionManager.d.ts +31 -0
- package/dist/imageEdit/ImageEditVersionManager.d.ts.map +1 -0
- package/dist/imageEdit/ImageEditVersionManager.js +39 -0
- package/dist/imageEdit/ImageEditVersionManager.js.map +1 -0
- package/dist/imageEdit/export.d.ts +33 -0
- package/dist/imageEdit/export.d.ts.map +1 -0
- package/dist/imageEdit/export.js +253 -0
- package/dist/imageEdit/export.js.map +1 -0
- package/dist/imageEdit/index.d.ts +14 -0
- package/dist/imageEdit/index.d.ts.map +1 -0
- package/dist/imageEdit/index.js +22 -0
- package/dist/imageEdit/index.js.map +1 -0
- package/dist/imageEdit/persistence.d.ts +15 -0
- package/dist/imageEdit/persistence.d.ts.map +1 -0
- package/dist/imageEdit/persistence.js +49 -0
- package/dist/imageEdit/persistence.js.map +1 -0
- package/dist/imageEdit/state.d.ts +42 -0
- package/dist/imageEdit/state.d.ts.map +1 -0
- package/dist/imageEdit/state.js +98 -0
- package/dist/imageEdit/state.js.map +1 -0
- package/dist/imageEdit/versionPaths.d.ts +27 -0
- package/dist/imageEdit/versionPaths.d.ts.map +1 -0
- package/dist/imageEdit/versionPaths.js +57 -0
- package/dist/imageEdit/versionPaths.js.map +1 -0
- package/dist/imageEdit/versions.d.ts +67 -0
- package/dist/imageEdit/versions.d.ts.map +1 -0
- package/dist/imageEdit/versions.js +161 -0
- package/dist/imageEdit/versions.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/jsonForm/chooseControl.d.ts +20 -0
- package/dist/jsonForm/chooseControl.d.ts.map +1 -0
- package/dist/jsonForm/chooseControl.js +82 -0
- package/dist/jsonForm/chooseControl.js.map +1 -0
- package/dist/jsonForm/evaluateWhen.d.ts +12 -0
- package/dist/jsonForm/evaluateWhen.d.ts.map +1 -0
- package/dist/jsonForm/evaluateWhen.js +65 -0
- package/dist/jsonForm/evaluateWhen.js.map +1 -0
- package/dist/jsonForm/index.d.ts +14 -0
- package/dist/jsonForm/index.d.ts.map +1 -0
- package/dist/jsonForm/index.js +12 -0
- package/dist/jsonForm/index.js.map +1 -0
- package/dist/jsonForm/inferSchema.d.ts +12 -0
- package/dist/jsonForm/inferSchema.d.ts.map +1 -0
- package/dist/jsonForm/inferSchema.js +15 -0
- package/dist/jsonForm/inferSchema.js.map +1 -0
- package/dist/jsonForm/pointer.d.ts +26 -0
- package/dist/jsonForm/pointer.d.ts.map +1 -0
- package/dist/jsonForm/pointer.js +102 -0
- package/dist/jsonForm/pointer.js.map +1 -0
- package/dist/jsonForm/types.d.ts +120 -0
- package/dist/jsonForm/types.d.ts.map +1 -0
- package/dist/jsonForm/types.js +10 -0
- package/dist/jsonForm/types.js.map +1 -0
- package/dist/markdown/convert.d.ts +11 -1
- package/dist/markdown/convert.d.ts.map +1 -1
- package/dist/markdown/convert.js +235 -15
- package/dist/markdown/convert.js.map +1 -1
- package/dist/markdown/index.d.ts +2 -2
- package/dist/markdown/index.d.ts.map +1 -1
- package/dist/markdown/index.js +1 -1
- package/dist/markdown/index.js.map +1 -1
- package/dist/markdown/types.d.ts +34 -1
- package/dist/markdown/types.d.ts.map +1 -1
- package/dist/markdown/utils.d.ts +40 -0
- package/dist/markdown/utils.d.ts.map +1 -1
- package/dist/markdown/utils.js +155 -0
- package/dist/markdown/utils.js.map +1 -1
- package/dist/recommend/index.d.ts +16 -0
- package/dist/recommend/index.d.ts.map +1 -0
- package/dist/recommend/index.js +15 -0
- package/dist/recommend/index.js.map +1 -0
- package/dist/recommend/templates.d.ts +39 -0
- package/dist/recommend/templates.d.ts.map +1 -0
- package/dist/recommend/templates.js +235 -0
- package/dist/recommend/templates.js.map +1 -0
- package/dist/schemas/BlockTemplates.d.ts +46 -8
- package/dist/schemas/BlockTemplates.d.ts.map +1 -1
- package/dist/schemas/BlockTemplates.js +3 -3
- package/dist/schemas/BlockTemplates.js.map +1 -1
- package/dist/schemas/ImageEditDoc.d.ts +81 -0
- package/dist/schemas/ImageEditDoc.d.ts.map +1 -0
- package/dist/schemas/ImageEditDoc.js +20 -0
- package/dist/schemas/ImageEditDoc.js.map +1 -0
- package/dist/schemas/Theme.d.ts +93 -23
- package/dist/schemas/Theme.d.ts.map +1 -1
- package/dist/schemas/Theme.js +80 -13
- package/dist/schemas/Theme.js.map +1 -1
- package/dist/schemas/colorUtils.d.ts +51 -0
- package/dist/schemas/colorUtils.d.ts.map +1 -0
- package/dist/schemas/colorUtils.js +154 -0
- package/dist/schemas/colorUtils.js.map +1 -0
- package/dist/schemas/fontStacks.d.ts +57 -0
- package/dist/schemas/fontStacks.d.ts.map +1 -0
- package/dist/schemas/fontStacks.js +227 -0
- package/dist/schemas/fontStacks.js.map +1 -0
- package/dist/schemas/index.d.ts +5 -0
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +4 -0
- package/dist/schemas/index.js.map +1 -1
- package/dist/schemas/themeCompile.d.ts +45 -0
- package/dist/schemas/themeCompile.d.ts.map +1 -0
- package/dist/schemas/themeCompile.js +160 -0
- package/dist/schemas/themeCompile.js.map +1 -0
- package/dist/schemas/themeLibrary.d.ts +11 -15
- package/dist/schemas/themeLibrary.d.ts.map +1 -1
- package/dist/schemas/themeLibrary.js +18 -499
- package/dist/schemas/themeLibrary.js.map +1 -1
- package/dist/schemas/themeValidator.d.ts +26 -0
- package/dist/schemas/themeValidator.d.ts.map +1 -0
- package/dist/schemas/themeValidator.js +352 -0
- package/dist/schemas/themeValidator.js.map +1 -0
- package/dist/schemas/themes/bold.json +48 -0
- package/dist/schemas/themes/cinematic.json +54 -0
- package/dist/schemas/themes/documentary.json +49 -0
- package/dist/schemas/themes/gezellig.json +44 -0
- package/dist/schemas/themes/index.d.ts +26 -0
- package/dist/schemas/themes/index.d.ts.map +1 -0
- package/dist/schemas/themes/index.js +49 -0
- package/dist/schemas/themes/index.js.map +1 -0
- package/dist/schemas/themes/magazine.json +44 -0
- package/dist/schemas/themes/minimalist.json +45 -0
- package/dist/schemas/themes/morning-light.json +42 -0
- package/dist/schemas/themes/standard-dark.json +50 -0
- package/dist/schemas/themes/standard.json +42 -0
- package/dist/schemas/themes/tech-dark.json +48 -0
- package/dist/schemas/themes/warm-earth.json +50 -0
- package/dist/storage/ScopedContentContainer.d.ts +44 -0
- package/dist/storage/ScopedContentContainer.d.ts.map +1 -0
- package/dist/storage/ScopedContentContainer.js +94 -0
- package/dist/storage/ScopedContentContainer.js.map +1 -0
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +1 -0
- package/dist/storage/index.js.map +1 -1
- package/dist/story/index.d.ts +53 -13
- package/dist/story/index.js +12 -4
- package/dist/themeLibrary-BHjJ0Qx6.d.ts +40 -0
- package/dist/{types-DYAzisMG.d.ts → types-BdZkdJ3z.d.ts} +35 -2
- package/dist/types-D98li1gV.d.ts +93 -0
- package/dist/versions/DocumentVersionManager.d.ts +31 -0
- package/dist/versions/DocumentVersionManager.d.ts.map +1 -0
- package/dist/versions/DocumentVersionManager.js +33 -0
- package/dist/versions/DocumentVersionManager.js.map +1 -0
- package/dist/versions/index.d.ts +29 -0
- package/dist/versions/index.d.ts.map +1 -0
- package/dist/versions/index.js +28 -0
- package/dist/versions/index.js.map +1 -0
- package/dist/versions/operations.d.ts +44 -0
- package/dist/versions/operations.d.ts.map +1 -0
- package/dist/versions/operations.js +190 -0
- package/dist/versions/operations.js.map +1 -0
- package/dist/versions/paths.d.ts +29 -0
- package/dist/versions/paths.d.ts.map +1 -0
- package/dist/versions/paths.js +66 -0
- package/dist/versions/paths.js.map +1 -0
- package/dist/versions/timestamp.d.ts +22 -0
- package/dist/versions/timestamp.d.ts.map +1 -0
- package/dist/versions/timestamp.js +44 -0
- package/dist/versions/timestamp.js.map +1 -0
- package/dist/versions/types.d.ts +92 -0
- package/dist/versions/types.d.ts.map +1 -0
- package/dist/versions/types.js +11 -0
- package/dist/versions/types.js.map +1 -0
- package/package.json +28 -1
- package/src/__tests__/colorUtils.test.ts +112 -0
- package/src/__tests__/getLayers.test.ts +32 -7
- package/src/__tests__/iconResolve.test.ts +122 -0
- package/src/__tests__/imageEditState.test.ts +74 -0
- package/src/__tests__/imageEditVersions.test.ts +169 -0
- package/src/__tests__/inferDocumentTitle.test.ts +50 -0
- package/src/__tests__/jsonForm.chooseControl.test.ts +86 -0
- package/src/__tests__/jsonForm.evaluateWhen.test.ts +59 -0
- package/src/__tests__/jsonForm.inferSchema.test.ts +25 -0
- package/src/__tests__/jsonForm.pointer.test.ts +103 -0
- package/src/__tests__/markdown.test.ts +44 -0
- package/src/__tests__/markdownIcons.test.ts +104 -0
- package/src/__tests__/markdownToDoc.test.ts +19 -4
- package/src/__tests__/recommendTemplates.test.ts +183 -0
- package/src/__tests__/scopedContentContainer.test.ts +89 -0
- package/src/__tests__/slideshowGenerator.test.ts +1 -1
- package/src/__tests__/surface.test.ts +68 -0
- package/src/__tests__/templateAnnotationParse.test.ts +42 -0
- package/src/__tests__/templates.test.ts +93 -9
- package/src/__tests__/themeCompile.test.ts +156 -0
- package/src/__tests__/themeValidator.test.ts +125 -0
- package/src/__tests__/versions.test.ts +415 -0
- package/src/doc/audioMapping.ts +95 -13
- package/src/doc/getLayers.ts +32 -21
- package/src/doc/markdownToDoc.ts +45 -7
- package/src/doc/templates/featureBlock.ts +202 -0
- package/src/doc/templates/fullBleedQuote.ts +13 -0
- package/src/doc/templates/index.ts +50 -16
- package/src/doc/templates/listBlock.ts +24 -5
- package/src/doc/templates/statHighlight.ts +13 -0
- package/src/doc/templates/titleBlock.ts +9 -0
- package/src/doc/utils/themeUtils.ts +8 -7
- package/src/generate/slideshowGenerator.ts +1 -1
- package/src/generate/templateMapper.ts +2 -2
- package/src/icons/iconData.ts +31 -0
- package/src/icons/index.ts +18 -0
- package/src/icons/resolve.ts +139 -0
- package/src/imageEdit/ImageEditVersionManager.ts +73 -0
- package/src/imageEdit/export.ts +326 -0
- package/src/imageEdit/index.ts +71 -0
- package/src/imageEdit/persistence.ts +62 -0
- package/src/imageEdit/state.ts +112 -0
- package/src/imageEdit/versionPaths.ts +57 -0
- package/src/imageEdit/versions.ts +231 -0
- package/src/index.ts +4 -0
- package/src/jsonForm/chooseControl.ts +88 -0
- package/src/jsonForm/evaluateWhen.ts +59 -0
- package/src/jsonForm/index.ts +22 -0
- package/src/jsonForm/inferSchema.ts +25 -0
- package/src/jsonForm/pointer.ts +109 -0
- package/src/jsonForm/types.ts +167 -0
- package/src/markdown/convert.ts +248 -15
- package/src/markdown/index.ts +4 -0
- package/src/markdown/types.ts +38 -1
- package/src/markdown/utils.ts +159 -0
- package/src/recommend/index.ts +16 -0
- package/src/recommend/templates.ts +273 -0
- package/src/schemas/BlockTemplates.ts +50 -7
- package/src/schemas/ImageEditDoc.ts +95 -0
- package/src/schemas/Theme.ts +152 -23
- package/src/schemas/colorUtils.ts +186 -0
- package/src/schemas/fontStacks.ts +257 -0
- package/src/schemas/index.ts +12 -0
- package/src/schemas/themeCompile.ts +203 -0
- package/src/schemas/themeLibrary.ts +18 -524
- package/src/schemas/themeValidator.ts +388 -0
- package/src/schemas/themes/bold.json +48 -0
- package/src/schemas/themes/cinematic.json +54 -0
- package/src/schemas/themes/documentary.json +49 -0
- package/src/schemas/themes/gezellig.json +44 -0
- package/src/schemas/themes/index.ts +53 -0
- package/src/schemas/themes/magazine.json +44 -0
- package/src/schemas/themes/minimalist.json +45 -0
- package/src/schemas/themes/morning-light.json +42 -0
- package/src/schemas/themes/standard-dark.json +50 -0
- package/src/schemas/themes/standard.json +42 -0
- package/src/schemas/themes/tech-dark.json +48 -0
- package/src/schemas/themes/warm-earth.json +50 -0
- package/src/storage/ScopedContentContainer.ts +113 -0
- package/src/storage/index.ts +1 -0
- package/src/versions/DocumentVersionManager.ts +70 -0
- package/src/versions/index.ts +54 -0
- package/src/versions/operations.ts +230 -0
- package/src/versions/paths.ts +66 -0
- package/src/versions/timestamp.ts +48 -0
- package/src/versions/types.ts +91 -0
- package/dist/chunk-53TZ2UTL.js +0 -470
- package/dist/chunk-53TZ2UTL.js.map +0 -1
- package/dist/chunk-7GF6RDED.js +0 -82
- package/dist/chunk-7GF6RDED.js.map +0 -1
- package/dist/chunk-CYQHG27J.js.map +0 -1
- package/dist/chunk-GAQLMORN.js.map +0 -1
- package/dist/chunk-LAZELBON.js.map +0 -1
- package/dist/chunk-QM5PKNPW.js.map +0 -1
- package/dist/chunk-TSG2OSE6.js.map +0 -1
- package/dist/chunk-XM4WSOHB.js +0 -92
- package/dist/chunk-XM4WSOHB.js.map +0 -1
- package/dist/themeLibrary-IP7EdyRq.d.ts +0 -44
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ImageEditDoc — JSON document describing a layered, editable image.
|
|
3
|
+
*
|
|
4
|
+
* This is the persistent state of the `<ImageEditor>` component. It lives
|
|
5
|
+
* inside a `<imagebasename>_files/` sidecar folder (exposed as a
|
|
6
|
+
* {@link ContentContainer}) at `state.json`, alongside referenced asset
|
|
7
|
+
* bytes in `assets/` and version snapshots in `.versions/`.
|
|
8
|
+
*
|
|
9
|
+
* Layers compose the existing core {@link Layer} types (image / text /
|
|
10
|
+
* shape) so renderers can share infrastructure with the doc system.
|
|
11
|
+
* Editor-specific metadata (name, visibility, lock, opacity, blendMode)
|
|
12
|
+
* lives in {@link EditorLayerMeta} and is merged onto each layer. The
|
|
13
|
+
* {@link Layer.animation} field is permitted but ignored by the image
|
|
14
|
+
* editor — animations are a slideshow concept.
|
|
15
|
+
*
|
|
16
|
+
* All asset paths in layers (e.g. `ImageLayer.content.src`) are
|
|
17
|
+
* relative to the sidecar root, keeping the document portable.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import type { ImageLayer, ShapeLayer, TextLayer } from './Doc.js';
|
|
21
|
+
|
|
22
|
+
// ============================================
|
|
23
|
+
// Layer type
|
|
24
|
+
// ============================================
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Per-layer editor metadata. Merged into each layer so the persisted
|
|
28
|
+
* shape is a single object. All fields optional; sensible defaults
|
|
29
|
+
* apply when absent (visible: true, locked: false, opacity: 1).
|
|
30
|
+
*/
|
|
31
|
+
export interface EditorLayerMeta {
|
|
32
|
+
/** Human-readable name shown in the layers panel. */
|
|
33
|
+
name?: string;
|
|
34
|
+
/** When false, the layer is hidden from rendering. Default true. */
|
|
35
|
+
visible?: boolean;
|
|
36
|
+
/** When true, the layer cannot be selected/edited. Default false. */
|
|
37
|
+
locked?: boolean;
|
|
38
|
+
/** 0..1 multiplier on the layer's alpha. Default 1. */
|
|
39
|
+
opacity?: number;
|
|
40
|
+
/**
|
|
41
|
+
* Canvas blend mode (matches the CSS / Canvas2D vocabulary).
|
|
42
|
+
* Default 'source-over' (normal compositing).
|
|
43
|
+
*/
|
|
44
|
+
blendMode?: GlobalCompositeOperation;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** A layer in an {@link ImageEditDoc}. */
|
|
48
|
+
export type ImageEditLayer = (ImageLayer | TextLayer | ShapeLayer) & EditorLayerMeta;
|
|
49
|
+
|
|
50
|
+
/** The layer kinds the image editor supports. */
|
|
51
|
+
export type ImageEditLayerKind = ImageEditLayer['type'];
|
|
52
|
+
|
|
53
|
+
// ============================================
|
|
54
|
+
// Document
|
|
55
|
+
// ============================================
|
|
56
|
+
|
|
57
|
+
/** Canvas dimensions and background. */
|
|
58
|
+
export interface ImageEditCanvas {
|
|
59
|
+
/** Canvas width in pixels. */
|
|
60
|
+
width: number;
|
|
61
|
+
/** Canvas height in pixels. */
|
|
62
|
+
height: number;
|
|
63
|
+
/**
|
|
64
|
+
* Background fill (CSS color, or `'transparent'` for an alpha canvas).
|
|
65
|
+
* Default: `'transparent'`.
|
|
66
|
+
*/
|
|
67
|
+
background?: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Optional document metadata. */
|
|
71
|
+
export interface ImageEditMeta {
|
|
72
|
+
/** Path to the original source image (sidecar-relative). Set when the doc is seeded from an existing image. */
|
|
73
|
+
sourcePath?: string;
|
|
74
|
+
/** ISO timestamp set on first save. */
|
|
75
|
+
createdAt?: string;
|
|
76
|
+
/** ISO timestamp updated on every save. */
|
|
77
|
+
updatedAt?: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The persisted image-editor document.
|
|
82
|
+
*
|
|
83
|
+
* Layers are composited back-to-front: `layers[0]` is the bottom of the stack
|
|
84
|
+
* (typically the base raster), `layers[layers.length - 1]` is the top.
|
|
85
|
+
*/
|
|
86
|
+
export interface ImageEditDoc {
|
|
87
|
+
/** Schema version. Bumped on breaking changes. */
|
|
88
|
+
version: 1;
|
|
89
|
+
/** Canvas configuration. */
|
|
90
|
+
canvas: ImageEditCanvas;
|
|
91
|
+
/** Layers, back-to-front. */
|
|
92
|
+
layers: ImageEditLayer[];
|
|
93
|
+
/** Optional metadata. */
|
|
94
|
+
meta?: ImageEditMeta;
|
|
95
|
+
}
|
package/src/schemas/Theme.ts
CHANGED
|
@@ -3,25 +3,41 @@
|
|
|
3
3
|
*
|
|
4
4
|
* A Theme bundles color palette, typography, visual style, render-style
|
|
5
5
|
* algorithm, and per-block color schemes into one JSON-serializable object.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
*
|
|
7
|
+
* Built-in themes and customizer-authored themes share this exact schema.
|
|
8
|
+
* Customizer-authored themes additionally specify `seedColors` so the few
|
|
9
|
+
* fields the user picked can be re-edited later; built-ins typically omit
|
|
10
|
+
* `seedColors` and ship with explicit `colors` already filled in.
|
|
8
11
|
*
|
|
9
12
|
* Design principles:
|
|
10
|
-
* - Fully JSON-serializable
|
|
11
|
-
* -
|
|
12
|
-
*
|
|
13
|
+
* - Fully JSON-serializable. No functions; no raw CSS font strings.
|
|
14
|
+
* - Font families are structured `FontFamily` references resolved by
|
|
15
|
+
* `resolveFontFamily()` at render time.
|
|
16
|
+
* - Doc carries an optional `themeId`; resolution happens at render time
|
|
17
|
+
* via `resolveTheme(id)`.
|
|
18
|
+
* - `createTheme` deep-merges a base theme with partial overrides;
|
|
19
|
+
* `compileTheme` fills in defaults and derives missing color slots from
|
|
20
|
+
* `seedColors`; both produce a complete `Theme`.
|
|
13
21
|
*/
|
|
14
22
|
|
|
15
23
|
import type { LayoutHints } from './LayoutStrategy.js';
|
|
16
24
|
import type { AnimationType, TransitionType } from './Doc.js';
|
|
17
25
|
import type { PersistentLayerConfig } from './BlockTemplates.js';
|
|
18
26
|
|
|
27
|
+
// ============================================
|
|
28
|
+
// Schema version
|
|
29
|
+
// ============================================
|
|
30
|
+
|
|
31
|
+
/** Current Theme schema version. Bump on breaking changes; loader migrates. */
|
|
32
|
+
export const THEME_SCHEMA_VERSION = '1' as const;
|
|
33
|
+
export type ThemeSchemaVersion = typeof THEME_SCHEMA_VERSION;
|
|
34
|
+
|
|
19
35
|
// ============================================
|
|
20
36
|
// Color Palette
|
|
21
37
|
// ============================================
|
|
22
38
|
|
|
23
39
|
/**
|
|
24
|
-
* Core color palette for a theme. Every color is a
|
|
40
|
+
* Core color palette for a theme. Every color is a `#rrggbb` hex string.
|
|
25
41
|
*/
|
|
26
42
|
export interface ThemeColorPalette {
|
|
27
43
|
/** Primary accent color */
|
|
@@ -55,20 +71,51 @@ export interface ThemeColorScheme {
|
|
|
55
71
|
accent: string;
|
|
56
72
|
}
|
|
57
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Optional authoring metadata. When present and `colors` is partial,
|
|
76
|
+
* `compileTheme` derives missing color slots from these seeds via OKLCh
|
|
77
|
+
* lightening / darkening. Round-trips a customizer-authored theme back
|
|
78
|
+
* into editable form.
|
|
79
|
+
*/
|
|
80
|
+
export interface ThemeSeedColors {
|
|
81
|
+
primary: string;
|
|
82
|
+
secondary?: string;
|
|
83
|
+
accent?: string;
|
|
84
|
+
background?: string;
|
|
85
|
+
text?: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
58
88
|
// ============================================
|
|
59
89
|
// Typography
|
|
60
90
|
// ============================================
|
|
61
91
|
|
|
92
|
+
/** Categorical bucket for a font family — drives default fallback. */
|
|
93
|
+
export type FontFamilyKind = 'sans' | 'serif' | 'mono' | 'display';
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Structured reference to a font family. Either a curated stack id (looked
|
|
97
|
+
* up in `AVAILABLE_FONT_STACKS`) or a custom user-supplied name with a
|
|
98
|
+
* structured fallback bucket. Themes never carry raw CSS family strings.
|
|
99
|
+
*/
|
|
100
|
+
export type FontFamily =
|
|
101
|
+
| { stackId: string }
|
|
102
|
+
| {
|
|
103
|
+
custom: {
|
|
104
|
+
name: string;
|
|
105
|
+
fallback: 'serif' | 'sans-serif' | 'monospace' | 'system-ui';
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
|
|
62
109
|
/**
|
|
63
110
|
* Typography settings for a theme.
|
|
64
111
|
*/
|
|
65
112
|
export interface ThemeTypography {
|
|
66
113
|
/** Font family for body / description text */
|
|
67
|
-
|
|
114
|
+
bodyFont: FontFamily;
|
|
68
115
|
/** Font family for titles and headings */
|
|
69
|
-
|
|
116
|
+
titleFont: FontFamily;
|
|
70
117
|
/** Font family for code / monospaced text (optional) */
|
|
71
|
-
|
|
118
|
+
monoFont?: FontFamily;
|
|
72
119
|
/** Multiplier applied to LayoutHints.titleScale (default 1.0) */
|
|
73
120
|
titleScale?: number;
|
|
74
121
|
/** Multiplier applied to LayoutHints.bodyScale (default 1.0) */
|
|
@@ -125,11 +172,8 @@ export interface RenderStyle {
|
|
|
125
172
|
/**
|
|
126
173
|
* Per-template behavioral hints. Keys are template names, values are
|
|
127
174
|
* string/number/boolean maps that templates can read to vary their output.
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
* ```
|
|
131
|
-
* { statHighlight: { entrance: 'dramatic' }, titleBlock: { showAccentLine: false } }
|
|
132
|
-
* ```
|
|
175
|
+
* Templates that consume hints publish a `hintSchema` export documenting
|
|
176
|
+
* the keys they recognise.
|
|
133
177
|
*/
|
|
134
178
|
templateHints?: Record<string, Record<string, string | number | boolean>>;
|
|
135
179
|
}
|
|
@@ -139,15 +183,20 @@ export interface RenderStyle {
|
|
|
139
183
|
// ============================================
|
|
140
184
|
|
|
141
185
|
/**
|
|
142
|
-
* A complete, JSON-serializable theme definition.
|
|
186
|
+
* A complete, JSON-serializable theme definition. Built-in and customizer-
|
|
187
|
+
* authored themes share this exact shape.
|
|
143
188
|
*/
|
|
144
189
|
export interface Theme {
|
|
190
|
+
/** Schema version. Always '1' for now. */
|
|
191
|
+
schemaVersion: ThemeSchemaVersion;
|
|
145
192
|
/** Unique identifier (e.g. "documentary") */
|
|
146
193
|
id: string;
|
|
147
194
|
/** Human-readable display name */
|
|
148
195
|
name: string;
|
|
149
196
|
/** Short description for theme pickers */
|
|
150
197
|
description?: string;
|
|
198
|
+
/** Optional authoring seeds (customizer fills these; built-ins typically omit) */
|
|
199
|
+
seedColors?: ThemeSeedColors;
|
|
151
200
|
/** Color palette */
|
|
152
201
|
colors: ThemeColorPalette;
|
|
153
202
|
/** Typography settings */
|
|
@@ -214,14 +263,6 @@ function deepMerge<T extends Record<string, unknown>>(target: T, source: DeepPar
|
|
|
214
263
|
* Create a new theme by deep-merging overrides onto a base theme.
|
|
215
264
|
* The returned theme gets its own `id` if one is provided in overrides,
|
|
216
265
|
* otherwise keeps the base theme's `id` suffixed with "-custom".
|
|
217
|
-
*
|
|
218
|
-
* @example
|
|
219
|
-
* ```ts
|
|
220
|
-
* const myTheme = createTheme(THEMES.documentary, {
|
|
221
|
-
* colors: { primary: '#ff0000' },
|
|
222
|
-
* typography: { bodyFontFamily: '"Inter", sans-serif' },
|
|
223
|
-
* });
|
|
224
|
-
* ```
|
|
225
266
|
*/
|
|
226
267
|
export function createTheme(base: Theme, overrides: DeepPartial<Theme>): Theme {
|
|
227
268
|
const merged = deepMerge(
|
|
@@ -231,5 +272,93 @@ export function createTheme(base: Theme, overrides: DeepPartial<Theme>): Theme {
|
|
|
231
272
|
if (!overrides.id && merged.id === base.id) {
|
|
232
273
|
merged.id = `${base.id}-custom`;
|
|
233
274
|
}
|
|
275
|
+
if (!merged.schemaVersion) merged.schemaVersion = THEME_SCHEMA_VERSION;
|
|
234
276
|
return merged;
|
|
235
277
|
}
|
|
278
|
+
|
|
279
|
+
// ============================================
|
|
280
|
+
// Surface Schemes — orthogonal to Theme
|
|
281
|
+
// ============================================
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* A Surface Scheme is the light/dark axis, orthogonal to the editorial
|
|
285
|
+
* identity of a Theme. A Theme chooses voice (serif vs sans, muted vs
|
|
286
|
+
* bold, documentary vs magazine); a SurfaceScheme chooses what the paper
|
|
287
|
+
* looks like. Any theme can render on either surface.
|
|
288
|
+
*/
|
|
289
|
+
export interface SurfaceScheme {
|
|
290
|
+
/** Identifier — 'light', 'dark', or a custom id. */
|
|
291
|
+
id: string;
|
|
292
|
+
background: string;
|
|
293
|
+
backgroundLight: string;
|
|
294
|
+
text: string;
|
|
295
|
+
textMuted: string;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/** Near-white paper with dark text — standard light mode. */
|
|
299
|
+
export const LIGHT_SURFACE: SurfaceScheme = {
|
|
300
|
+
id: 'light',
|
|
301
|
+
background: '#ffffff',
|
|
302
|
+
backgroundLight: '#f5f5f5',
|
|
303
|
+
text: '#1a1a1a',
|
|
304
|
+
textMuted: '#666666',
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
/** Dark charcoal paper with light text — standard dark mode. */
|
|
308
|
+
export const DARK_SURFACE: SurfaceScheme = {
|
|
309
|
+
id: 'dark',
|
|
310
|
+
background: '#1a202c',
|
|
311
|
+
backgroundLight: '#2d3748',
|
|
312
|
+
text: '#f0f0f0',
|
|
313
|
+
textMuted: '#a0aec0',
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Overlay a SurfaceScheme's surface colors onto a Theme's palette,
|
|
318
|
+
* leaving everything else (primary, highlight, warning, typography,
|
|
319
|
+
* style, renderStyle, colorSchemes) untouched.
|
|
320
|
+
*/
|
|
321
|
+
export function applySurface(theme: Theme, surface: SurfaceScheme): Theme {
|
|
322
|
+
return {
|
|
323
|
+
...theme,
|
|
324
|
+
colors: {
|
|
325
|
+
...theme.colors,
|
|
326
|
+
background: surface.background,
|
|
327
|
+
backgroundLight: surface.backgroundLight,
|
|
328
|
+
text: surface.text,
|
|
329
|
+
textMuted: surface.textMuted,
|
|
330
|
+
},
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// ============================================
|
|
335
|
+
// Runtime registry — for custom themes
|
|
336
|
+
// ============================================
|
|
337
|
+
|
|
338
|
+
const CUSTOM_THEME_REGISTRY = new Map<string, Theme>();
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Register a Theme so it can be looked up by id via `resolveTheme(id)`.
|
|
342
|
+
* Lets `Doc.themeId` round-trip through Doc serialization for custom themes.
|
|
343
|
+
*
|
|
344
|
+
* Registered themes take precedence over built-ins with the same id.
|
|
345
|
+
*/
|
|
346
|
+
export function registerTheme(theme: Theme): void {
|
|
347
|
+
CUSTOM_THEME_REGISTRY.set(theme.id, theme);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/** Remove a previously registered theme. */
|
|
351
|
+
export function unregisterTheme(id: string): void {
|
|
352
|
+
CUSTOM_THEME_REGISTRY.delete(id);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/** Snapshot of all currently registered (non-built-in) themes. */
|
|
356
|
+
export function getRegisteredThemes(): Theme[] {
|
|
357
|
+
return Array.from(CUSTOM_THEME_REGISTRY.values());
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/** @internal — used by themeLibrary's `resolveTheme` to check the registry first. */
|
|
361
|
+
export function lookupRegisteredTheme(id: string | undefined): Theme | undefined {
|
|
362
|
+
if (!id) return undefined;
|
|
363
|
+
return CUSTOM_THEME_REGISTRY.get(id);
|
|
364
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Color Utilities
|
|
3
|
+
*
|
|
4
|
+
* Pure-JS color math used by theme compilation and contrast checks.
|
|
5
|
+
* No dependencies. Operates on `#rrggbb` hex strings.
|
|
6
|
+
*
|
|
7
|
+
* Internally uses OKLCh — perceptually uniform, so lightening by 0.1
|
|
8
|
+
* looks like the same change at any starting point. Out-of-gamut
|
|
9
|
+
* results are clamped to sRGB.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const HEX_RE = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;
|
|
13
|
+
|
|
14
|
+
/** Test whether a string is a valid `#rgb` or `#rrggbb` hex color. */
|
|
15
|
+
export function isHex(value: string): boolean {
|
|
16
|
+
return HEX_RE.test(value);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Parse `#rgb` or `#rrggbb` into 0..1 sRGB triplet. Returns null on failure. */
|
|
20
|
+
function parseHex(hex: string): [number, number, number] | null {
|
|
21
|
+
if (!HEX_RE.test(hex)) return null;
|
|
22
|
+
let body = hex.slice(1);
|
|
23
|
+
if (body.length === 3)
|
|
24
|
+
body = body
|
|
25
|
+
.split('')
|
|
26
|
+
.map((c) => c + c)
|
|
27
|
+
.join('');
|
|
28
|
+
return [
|
|
29
|
+
parseInt(body.slice(0, 2), 16) / 255,
|
|
30
|
+
parseInt(body.slice(2, 4), 16) / 255,
|
|
31
|
+
parseInt(body.slice(4, 6), 16) / 255,
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function toHex(rgb: [number, number, number]): string {
|
|
36
|
+
const ch = (v: number) => {
|
|
37
|
+
const c = Math.max(0, Math.min(255, Math.round(v * 255)));
|
|
38
|
+
return c.toString(16).padStart(2, '0');
|
|
39
|
+
};
|
|
40
|
+
return '#' + ch(rgb[0]) + ch(rgb[1]) + ch(rgb[2]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function srgbToLinear(c: number): number {
|
|
44
|
+
return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function linearToSrgb(c: number): number {
|
|
48
|
+
return c <= 0.0031308 ? c * 12.92 : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface OKLCh {
|
|
52
|
+
L: number;
|
|
53
|
+
C: number;
|
|
54
|
+
h: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function rgbToOklch(rgb: [number, number, number]): OKLCh {
|
|
58
|
+
const [sr, sg, sb] = rgb;
|
|
59
|
+
const r = srgbToLinear(sr);
|
|
60
|
+
const g = srgbToLinear(sg);
|
|
61
|
+
const b = srgbToLinear(sb);
|
|
62
|
+
|
|
63
|
+
const l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;
|
|
64
|
+
const m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;
|
|
65
|
+
const s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;
|
|
66
|
+
|
|
67
|
+
const l_ = Math.cbrt(l);
|
|
68
|
+
const m_ = Math.cbrt(m);
|
|
69
|
+
const s_ = Math.cbrt(s);
|
|
70
|
+
|
|
71
|
+
const L = 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_;
|
|
72
|
+
const a = 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_;
|
|
73
|
+
const bb = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_;
|
|
74
|
+
|
|
75
|
+
const C = Math.sqrt(a * a + bb * bb);
|
|
76
|
+
let h = (Math.atan2(bb, a) * 180) / Math.PI;
|
|
77
|
+
if (h < 0) h += 360;
|
|
78
|
+
return { L, C, h };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function oklchToRgb({ L, C, h }: OKLCh): [number, number, number] {
|
|
82
|
+
const hr = (h * Math.PI) / 180;
|
|
83
|
+
const a = C * Math.cos(hr);
|
|
84
|
+
const bb = C * Math.sin(hr);
|
|
85
|
+
|
|
86
|
+
const l_ = L + 0.3963377774 * a + 0.2158037573 * bb;
|
|
87
|
+
const m_ = L - 0.1055613458 * a - 0.0638541728 * bb;
|
|
88
|
+
const s_ = L - 0.0894841775 * a - 1.291485548 * bb;
|
|
89
|
+
|
|
90
|
+
const l = l_ * l_ * l_;
|
|
91
|
+
const m = m_ * m_ * m_;
|
|
92
|
+
const s = s_ * s_ * s_;
|
|
93
|
+
|
|
94
|
+
const r = +4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s;
|
|
95
|
+
const g = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s;
|
|
96
|
+
const b = -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s;
|
|
97
|
+
|
|
98
|
+
return [
|
|
99
|
+
Math.max(0, Math.min(1, linearToSrgb(r))),
|
|
100
|
+
Math.max(0, Math.min(1, linearToSrgb(g))),
|
|
101
|
+
Math.max(0, Math.min(1, linearToSrgb(b))),
|
|
102
|
+
];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Lighten a color by `amount` (0..1) in OKLCh L space.
|
|
107
|
+
* Falls back to the input on parse failure.
|
|
108
|
+
*/
|
|
109
|
+
export function oklchLighten(hex: string, amount: number): string {
|
|
110
|
+
const rgb = parseHex(hex);
|
|
111
|
+
if (!rgb) return hex;
|
|
112
|
+
const lch = rgbToOklch(rgb);
|
|
113
|
+
lch.L = Math.max(0, Math.min(1, lch.L + amount));
|
|
114
|
+
return toHex(oklchToRgb(lch));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Darken a color by `amount` (0..1) in OKLCh L space.
|
|
119
|
+
* Falls back to the input on parse failure.
|
|
120
|
+
*/
|
|
121
|
+
export function oklchDarken(hex: string, amount: number): string {
|
|
122
|
+
return oklchLighten(hex, -amount);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Adjust the OKLCh chroma of a color by a multiplier (e.g. 0.7 to mute).
|
|
127
|
+
*/
|
|
128
|
+
export function oklchSetChroma(hex: string, multiplier: number): string {
|
|
129
|
+
const rgb = parseHex(hex);
|
|
130
|
+
if (!rgb) return hex;
|
|
131
|
+
const lch = rgbToOklch(rgb);
|
|
132
|
+
lch.C = Math.max(0, lch.C * multiplier);
|
|
133
|
+
return toHex(oklchToRgb(lch));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* WCAG relative luminance of a hex color, returned as 0..1.
|
|
138
|
+
*/
|
|
139
|
+
export function relativeLuminance(hex: string): number {
|
|
140
|
+
const rgb = parseHex(hex);
|
|
141
|
+
if (!rgb) return 0;
|
|
142
|
+
const [r, g, b] = rgb.map(srgbToLinear) as [number, number, number];
|
|
143
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* WCAG contrast ratio between two hex colors. Returns 1..21.
|
|
148
|
+
*/
|
|
149
|
+
export function contrastRatio(a: string, b: string): number {
|
|
150
|
+
const la = relativeLuminance(a);
|
|
151
|
+
const lb = relativeLuminance(b);
|
|
152
|
+
const lighter = Math.max(la, lb);
|
|
153
|
+
const darker = Math.min(la, lb);
|
|
154
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Pick a near-white or near-black text color that contrasts well against `bg`.
|
|
159
|
+
*/
|
|
160
|
+
export function pickContrastingText(bg: string, light = '#f7fafc', dark = '#1a202c'): string {
|
|
161
|
+
return contrastRatio(bg, dark) >= contrastRatio(bg, light) ? dark : light;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Derive a 5-step lighter→darker scale from a seed color.
|
|
166
|
+
* Stops are evenly spaced in OKLCh L space around the seed.
|
|
167
|
+
* `spread` controls amplitude (0.05 = subtle, 0.15 = balanced, 0.22 = high).
|
|
168
|
+
*/
|
|
169
|
+
export function deriveScale(
|
|
170
|
+
seedHex: string,
|
|
171
|
+
spread = 0.15,
|
|
172
|
+
): {
|
|
173
|
+
lighter2: string;
|
|
174
|
+
lighter1: string;
|
|
175
|
+
base: string;
|
|
176
|
+
darker1: string;
|
|
177
|
+
darker2: string;
|
|
178
|
+
} {
|
|
179
|
+
return {
|
|
180
|
+
lighter2: oklchLighten(seedHex, spread),
|
|
181
|
+
lighter1: oklchLighten(seedHex, spread / 2),
|
|
182
|
+
base: seedHex,
|
|
183
|
+
darker1: oklchDarken(seedHex, spread / 2),
|
|
184
|
+
darker2: oklchDarken(seedHex, spread),
|
|
185
|
+
};
|
|
186
|
+
}
|