omni-color 0.1.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/LICENSE +7 -0
- package/README.md +1042 -0
- package/dist/__test__/color-interop.test.d.ts +1 -0
- package/dist/__test__/color-interop.test.js +82 -0
- package/dist/__test__/comparison_culori.test.d.ts +1 -0
- package/dist/__test__/comparison_culori.test.js +169 -0
- package/dist/__test__/interop-chroma.test.d.ts +1 -0
- package/dist/__test__/interop-chroma.test.js +676 -0
- package/dist/__test__/interop-tinycolor.test.d.ts +1 -0
- package/dist/__test__/interop-tinycolor.test.js +499 -0
- package/dist/color/__test__/baseColor.test.d.ts +2 -0
- package/dist/color/__test__/baseColor.test.d.ts.map +1 -0
- package/dist/color/__test__/baseColor.test.js +34 -0
- package/dist/color/__test__/baseColor.test.js.map +1 -0
- package/dist/color/__test__/blank.d.ts +1 -0
- package/dist/color/__test__/blank.js +3 -0
- package/dist/color/__test__/color.test.d.ts +1 -0
- package/dist/color/__test__/color.test.js +1073 -0
- package/dist/color/__test__/colorSpaces.test.d.ts +1 -0
- package/dist/color/__test__/colorSpaces.test.js +69 -0
- package/dist/color/__test__/combinations.test.d.ts +1 -0
- package/dist/color/__test__/combinations.test.js +665 -0
- package/dist/color/__test__/conversions.test.d.ts +1 -0
- package/dist/color/__test__/conversions.test.js +719 -0
- package/dist/color/__test__/deltaE.test.d.ts +1 -0
- package/dist/color/__test__/deltaE.test.js +120 -0
- package/dist/color/__test__/formats.test.d.ts +1 -0
- package/dist/color/__test__/formats.test.js +514 -0
- package/dist/color/__test__/gradients.test.d.ts +1 -0
- package/dist/color/__test__/gradients.test.js +414 -0
- package/dist/color/__test__/harmonies.test.d.ts +1 -0
- package/dist/color/__test__/harmonies.test.js +676 -0
- package/dist/color/__test__/manipulations.test.d.ts +1 -0
- package/dist/color/__test__/manipulations.test.js +264 -0
- package/dist/color/__test__/names.test.d.ts +1 -0
- package/dist/color/__test__/names.test.js +67 -0
- package/dist/color/__test__/parse.test.d.ts +1 -0
- package/dist/color/__test__/parse.test.js +256 -0
- package/dist/color/__test__/random.test.d.ts +1 -0
- package/dist/color/__test__/random.test.js +262 -0
- package/dist/color/__test__/readability.test.d.ts +1 -0
- package/dist/color/__test__/readability.test.js +2596 -0
- package/dist/color/__test__/srgb.test.d.ts +1 -0
- package/dist/color/__test__/srgb.test.js +43 -0
- package/dist/color/__test__/swatch.test.d.ts +1 -0
- package/dist/color/__test__/swatch.test.js +267 -0
- package/dist/color/__test__/temperature.test.d.ts +1 -0
- package/dist/color/__test__/temperature.test.js +223 -0
- package/dist/color/__test__/utils.test.d.ts +1 -0
- package/dist/color/__test__/utils.test.js +409 -0
- package/dist/color/__test__/validations.test.d.ts +1 -0
- package/dist/color/__test__/validations.test.js +239 -0
- package/dist/color/color.constants.d.ts +4 -0
- package/dist/color/color.constants.d.ts.map +1 -0
- package/dist/color/color.constants.js +152 -0
- package/dist/color/color.constants.js.map +1 -0
- package/dist/color/color.consts.d.ts +4 -0
- package/dist/color/color.consts.js +152 -0
- package/dist/color/color.d.ts +788 -0
- package/dist/color/color.d.ts.map +1 -0
- package/dist/color/color.helpers.d.ts +6 -0
- package/dist/color/color.helpers.js +4 -0
- package/dist/color/color.js +919 -0
- package/dist/color/color.js.map +1 -0
- package/dist/color/colorSpaces.d.ts +15 -0
- package/dist/color/colorSpaces.js +127 -0
- package/dist/color/combinations.d.ts +45 -0
- package/dist/color/combinations.js +562 -0
- package/dist/color/conversions.d.ts +16 -0
- package/dist/color/conversions.d.ts.map +1 -0
- package/dist/color/conversions.js +705 -0
- package/dist/color/conversions.js.map +1 -0
- package/dist/color/deltaE.d.ts +59 -0
- package/dist/color/deltaE.js +110 -0
- package/dist/color/formats.d.ts +128 -0
- package/dist/color/formats.d.ts.map +1 -0
- package/dist/color/formats.js +153 -0
- package/dist/color/formats.js.map +1 -0
- package/dist/color/gradients.d.ts +49 -0
- package/dist/color/gradients.js +672 -0
- package/dist/color/harmonies.d.ts +18 -0
- package/dist/color/harmonies.js +128 -0
- package/dist/color/manipulations.d.ts +29 -0
- package/dist/color/manipulations.js +106 -0
- package/dist/color/names.d.ts +38 -0
- package/dist/color/names.js +108 -0
- package/dist/color/parse.d.ts +2 -0
- package/dist/color/parse.js +437 -0
- package/dist/color/random.d.ts +30 -0
- package/dist/color/random.js +65 -0
- package/dist/color/readability.d.ts +53 -0
- package/dist/color/readability.js +284 -0
- package/dist/color/srgb.d.ts +8 -0
- package/dist/color/srgb.js +33 -0
- package/dist/color/swatch.d.ts +49 -0
- package/dist/color/swatch.js +118 -0
- package/dist/color/temperature.d.ts +26 -0
- package/dist/color/temperature.js +141 -0
- package/dist/color/utils.d.ts +49 -0
- package/dist/color/utils.d.ts.map +1 -0
- package/dist/color/utils.js +104 -0
- package/dist/color/utils.js.map +1 -0
- package/dist/color/validations.d.ts +2 -0
- package/dist/color/validations.d.ts.map +1 -0
- package/dist/color/validations.js +178 -0
- package/dist/color/validations.js.map +1 -0
- package/dist/demo/src/AppFooter.d.ts +1 -0
- package/dist/demo/src/AppFooter.js +4 -0
- package/dist/demo/src/AppHeader.d.ts +5 -0
- package/dist/demo/src/AppHeader.js +6 -0
- package/dist/demo/src/components/Card.d.ts +9 -0
- package/dist/demo/src/components/Card.js +9 -0
- package/dist/demo/src/components/Chip.d.ts +21 -0
- package/dist/demo/src/components/Chip.js +23 -0
- package/dist/demo/src/components/ColorBox.d.ts +16 -0
- package/dist/demo/src/components/ColorBox.js +45 -0
- package/dist/demo/src/components/ColorInfoCard.d.ts +7 -0
- package/dist/demo/src/components/ColorInfoCard.js +50 -0
- package/dist/demo/src/components/ExpandableCodeSnippet.d.ts +5 -0
- package/dist/demo/src/components/ExpandableCodeSnippet.js +17 -0
- package/dist/demo/src/components/Icon.d.ts +11 -0
- package/dist/demo/src/components/Icon.js +50 -0
- package/dist/demo/src/components/Icon.types.d.ts +14 -0
- package/dist/demo/src/components/Icon.types.js +15 -0
- package/dist/demo/src/components/SectionContainer.d.ts +10 -0
- package/dist/demo/src/components/SectionContainer.js +12 -0
- package/dist/demo/src/components/VSpace.d.ts +5 -0
- package/dist/demo/src/components/VSpace.js +4 -0
- package/dist/demo/src/components/inputs/Checkbox.d.ts +7 -0
- package/dist/demo/src/components/inputs/Checkbox.js +4 -0
- package/dist/demo/src/components/inputs/InputGroup.d.ts +6 -0
- package/dist/demo/src/components/inputs/InputGroup.js +4 -0
- package/dist/demo/src/components/inputs/NumberInput.d.ts +10 -0
- package/dist/demo/src/components/inputs/NumberInput.js +8 -0
- package/dist/demo/src/components/inputs/Select.d.ts +12 -0
- package/dist/demo/src/components/inputs/Select.js +6 -0
- package/dist/demo/src/components/inputs/Slider.d.ts +10 -0
- package/dist/demo/src/components/inputs/Slider.js +4 -0
- package/dist/demo/src/components/utils.d.ts +17 -0
- package/dist/demo/src/components/utils.js +24 -0
- package/dist/demo/src/demo/ColorDemo.d.ts +1 -0
- package/dist/demo/src/demo/ColorDemo.js +45 -0
- package/dist/demo/src/demo/ColorHarmonyDemo.d.ts +6 -0
- package/dist/demo/src/demo/ColorHarmonyDemo.js +18 -0
- package/dist/demo/src/demo/ColorInfo.d.ts +6 -0
- package/dist/demo/src/demo/ColorInfo.js +14 -0
- package/dist/demo/src/demo/ColorInput.d.ts +7 -0
- package/dist/demo/src/demo/ColorInput.js +58 -0
- package/dist/demo/src/demo/ColorManipulationDemo.d.ts +6 -0
- package/dist/demo/src/demo/ColorManipulationDemo.js +63 -0
- package/dist/demo/src/demo/ColorSwatch.d.ts +13 -0
- package/dist/demo/src/demo/ColorSwatch.js +15 -0
- package/dist/demo/src/demo/ReadabilityDemo.d.ts +6 -0
- package/dist/demo/src/demo/ReadabilityDemo.js +24 -0
- package/dist/demo/src/demo/combinations/AverageColorsOptionInputs.d.ts +7 -0
- package/dist/demo/src/demo/combinations/AverageColorsOptionInputs.js +7 -0
- package/dist/demo/src/demo/combinations/BlendColorsOptionInputs.d.ts +7 -0
- package/dist/demo/src/demo/combinations/BlendColorsOptionInputs.js +13 -0
- package/dist/demo/src/demo/combinations/ColorCombinationDemo.d.ts +6 -0
- package/dist/demo/src/demo/combinations/ColorCombinationDemo.js +78 -0
- package/dist/demo/src/demo/combinations/MixColorsOptionInputs.d.ts +7 -0
- package/dist/demo/src/demo/combinations/MixColorsOptionInputs.js +10 -0
- package/dist/demo/src/demo/combinations/colorCombinationDemo.consts.d.ts +4 -0
- package/dist/demo/src/demo/combinations/colorCombinationDemo.consts.js +12 -0
- package/dist/demo/src/demo/gradients/GradientOptionInputs.d.ts +10 -0
- package/dist/demo/src/demo/gradients/GradientOptionInputs.js +42 -0
- package/dist/demo/src/demo/gradients/GradientThroughCard.d.ts +6 -0
- package/dist/demo/src/demo/gradients/GradientThroughCard.js +50 -0
- package/dist/demo/src/demo/gradients/GradientToCard.d.ts +6 -0
- package/dist/demo/src/demo/gradients/GradientToCard.js +54 -0
- package/dist/demo/src/demo/gradients/GradientsDemo.d.ts +6 -0
- package/dist/demo/src/demo/gradients/GradientsDemo.js +6 -0
- package/dist/demo/src/demo/gradients/gradientOptions.consts.d.ts +3 -0
- package/dist/demo/src/demo/gradients/gradientOptions.consts.js +16 -0
- package/dist/demo/src/demo/palette/ColorPaletteDemo.d.ts +6 -0
- package/dist/demo/src/demo/palette/ColorPaletteDemo.js +26 -0
- package/dist/demo/src/demo/palette/PaletteGenerationOptions.d.ts +8 -0
- package/dist/demo/src/demo/palette/PaletteGenerationOptions.js +53 -0
- package/dist/demo/src/demo/palette/PaletteHarmonyOptions.d.ts +7 -0
- package/dist/demo/src/demo/palette/PaletteHarmonyOptions.js +5 -0
- package/dist/demo/src/main.d.ts +1 -0
- package/dist/demo/src/main.js +14 -0
- package/dist/demo/src/pages/DemoPage.d.ts +1 -0
- package/dist/demo/src/pages/DemoPage.js +28 -0
- package/dist/demo/src/pages/PlaygroundPage.d.ts +1 -0
- package/dist/demo/src/pages/PlaygroundPage.js +24 -0
- package/dist/demo/src/playground/Playground.d.ts +1 -0
- package/dist/demo/src/playground/Playground.js +42 -0
- package/dist/demo/src/playground/playgroundUtils.d.ts +16 -0
- package/dist/demo/src/playground/playgroundUtils.js +202 -0
- package/dist/demo/src/seo/PageHead.d.ts +9 -0
- package/dist/demo/src/seo/PageHead.js +76 -0
- package/dist/demo/src/seo/StructuredData.d.ts +6 -0
- package/dist/demo/src/seo/StructuredData.js +13 -0
- package/dist/demo/src/toast/ToastProvider.d.ts +2 -0
- package/dist/demo/src/toast/ToastProvider.js +62 -0
- package/dist/demo/src/toast/index.d.ts +2 -0
- package/dist/demo/src/toast/index.js +2 -0
- package/dist/demo/src/toast/toastBus.d.ts +13 -0
- package/dist/demo/src/toast/toastBus.js +27 -0
- package/dist/index.d.ts +1233 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5235 -0
- package/dist/index.js.map +1 -0
- package/dist/palette/__test__/palette.test.d.ts +1 -0
- package/dist/palette/__test__/palette.test.js +397 -0
- package/dist/palette/palette.d.ts +41 -0
- package/dist/palette/palette.js +126 -0
- package/dist/src/__test__/interop-chroma.test.d.ts +1 -0
- package/dist/src/__test__/interop-chroma.test.js +673 -0
- package/dist/src/__test__/interop-tinycolor.test.d.ts +1 -0
- package/dist/src/__test__/interop-tinycolor.test.js +499 -0
- package/dist/src/color/__test__/color.test.d.ts +1 -0
- package/dist/src/color/__test__/color.test.js +1071 -0
- package/dist/src/color/__test__/colorSpaces.test.d.ts +1 -0
- package/dist/src/color/__test__/colorSpaces.test.js +69 -0
- package/dist/src/color/__test__/combinations.test.d.ts +1 -0
- package/dist/src/color/__test__/combinations.test.js +665 -0
- package/dist/src/color/__test__/conversions.test.d.ts +1 -0
- package/dist/src/color/__test__/conversions.test.js +719 -0
- package/dist/src/color/__test__/deltaE.test.d.ts +1 -0
- package/dist/src/color/__test__/deltaE.test.js +120 -0
- package/dist/src/color/__test__/formats.test.d.ts +1 -0
- package/dist/src/color/__test__/formats.test.js +470 -0
- package/dist/src/color/__test__/gradients.test.d.ts +1 -0
- package/dist/src/color/__test__/gradients.test.js +414 -0
- package/dist/src/color/__test__/harmonies.test.d.ts +1 -0
- package/dist/src/color/__test__/harmonies.test.js +734 -0
- package/dist/src/color/__test__/manipulations.test.d.ts +1 -0
- package/dist/src/color/__test__/manipulations.test.js +264 -0
- package/dist/src/color/__test__/names.test.d.ts +1 -0
- package/dist/src/color/__test__/names.test.js +67 -0
- package/dist/src/color/__test__/parse.test.d.ts +1 -0
- package/dist/src/color/__test__/parse.test.js +251 -0
- package/dist/src/color/__test__/random.test.d.ts +1 -0
- package/dist/src/color/__test__/random.test.js +262 -0
- package/dist/src/color/__test__/readability.test.d.ts +1 -0
- package/dist/src/color/__test__/readability.test.js +2596 -0
- package/dist/src/color/__test__/swatch.test.d.ts +1 -0
- package/dist/src/color/__test__/swatch.test.js +267 -0
- package/dist/src/color/__test__/temperature.test.d.ts +1 -0
- package/dist/src/color/__test__/temperature.test.js +223 -0
- package/dist/src/color/__test__/utils.test.d.ts +1 -0
- package/dist/src/color/__test__/utils.test.js +409 -0
- package/dist/src/color/__test__/validations.test.d.ts +1 -0
- package/dist/src/color/__test__/validations.test.js +239 -0
- package/dist/src/color/color.consts.d.ts +4 -0
- package/dist/src/color/color.consts.js +152 -0
- package/dist/src/color/color.d.ts +775 -0
- package/dist/src/color/color.js +903 -0
- package/dist/src/color/colorSpaces.d.ts +15 -0
- package/dist/src/color/colorSpaces.js +127 -0
- package/dist/src/color/combinations.d.ts +45 -0
- package/dist/src/color/combinations.js +557 -0
- package/dist/src/color/conversions.d.ts +16 -0
- package/dist/src/color/conversions.js +705 -0
- package/dist/src/color/deltaE.d.ts +59 -0
- package/dist/src/color/deltaE.js +110 -0
- package/dist/src/color/formats.d.ts +126 -0
- package/dist/src/color/formats.js +150 -0
- package/dist/src/color/gradients.d.ts +49 -0
- package/dist/src/color/gradients.js +673 -0
- package/dist/src/color/harmonies.d.ts +18 -0
- package/dist/src/color/harmonies.js +129 -0
- package/dist/src/color/manipulations.d.ts +29 -0
- package/dist/src/color/manipulations.js +107 -0
- package/dist/src/color/names.d.ts +38 -0
- package/dist/src/color/names.js +108 -0
- package/dist/src/color/parse.d.ts +2 -0
- package/dist/src/color/parse.js +438 -0
- package/dist/src/color/random.d.ts +30 -0
- package/dist/src/color/random.js +65 -0
- package/dist/src/color/readability.d.ts +53 -0
- package/dist/src/color/readability.js +284 -0
- package/dist/src/color/swatch.d.ts +49 -0
- package/dist/src/color/swatch.js +117 -0
- package/dist/src/color/temperature.d.ts +26 -0
- package/dist/src/color/temperature.js +142 -0
- package/dist/src/color/utils.d.ts +57 -0
- package/dist/src/color/utils.js +142 -0
- package/dist/src/color/validations.d.ts +2 -0
- package/dist/src/color/validations.js +178 -0
- package/dist/src/index.d.ts +20 -0
- package/dist/src/index.js +2 -0
- package/dist/src/palette/__test__/palette.test.d.ts +1 -0
- package/dist/src/palette/__test__/palette.test.js +397 -0
- package/dist/src/palette/palette.d.ts +41 -0
- package/dist/src/palette/palette.js +127 -0
- package/dist/src/utils.d.ts +20 -0
- package/dist/src/utils.js +42 -0
- package/dist/utils.d.ts +20 -0
- package/dist/utils.js +42 -0
- package/package.json +96 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { Color } from '../../../dist';
|
|
2
|
+
function getRandomElementFromArray(arr) {
|
|
3
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
4
|
+
}
|
|
5
|
+
const UPDATE_COLOR_METHOD_EXAMPLES = [
|
|
6
|
+
{ method: 'setAlpha', argOptions: [0.1, 0.3, 0.5, 0.7, 0.9] },
|
|
7
|
+
{ method: 'spin', argOptions: [-180, -90, -45, 45, 90, 180, 270] },
|
|
8
|
+
{ method: 'brighten', argOptions: [undefined, 20, 30, 40] },
|
|
9
|
+
{ method: 'darken', argOptions: [undefined, 20, 30, 40] },
|
|
10
|
+
{ method: 'saturate', argOptions: [undefined, 20, 30, 40] },
|
|
11
|
+
{ method: 'desaturate', argOptions: [undefined, 20, 30, 40] },
|
|
12
|
+
{ method: 'grayscale' },
|
|
13
|
+
{
|
|
14
|
+
method: 'mix',
|
|
15
|
+
argOptions: [
|
|
16
|
+
'[new Color("red")], { space: "RGB" }',
|
|
17
|
+
'[new Color("green")], { space: "HSL" }',
|
|
18
|
+
'[new Color("blue"), new Color("#fff")], { space: "LCH" }',
|
|
19
|
+
'[new Color(), new Color()], { space: "OKLCH" }',
|
|
20
|
+
],
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
method: 'blend',
|
|
24
|
+
argOptions: [
|
|
25
|
+
'new Color("red")',
|
|
26
|
+
'new Color("green"), { mode: "MULTIPLY" }',
|
|
27
|
+
'new Color("blue"), { mode: "OVERLAY" }',
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
method: 'average',
|
|
32
|
+
argOptions: [
|
|
33
|
+
'[new Color()]',
|
|
34
|
+
'[new Color("red"), new Color("green")]',
|
|
35
|
+
'[new Color("sky blue")], { weights: [0.75, 0.25] }',
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
const GET_RESULT_COLOR_EXAMPLES = [
|
|
40
|
+
'clone()',
|
|
41
|
+
'getComplementaryColors()[0]',
|
|
42
|
+
'getComplementaryColors()[1]',
|
|
43
|
+
'getSplitComplementaryColors()[0]',
|
|
44
|
+
'getSplitComplementaryColors()[1]',
|
|
45
|
+
'getSplitComplementaryColors()[2]',
|
|
46
|
+
'getSquareHarmonyColors()[0]',
|
|
47
|
+
'getSquareHarmonyColors()[1]',
|
|
48
|
+
'getSquareHarmonyColors()[2]',
|
|
49
|
+
'getSquareHarmonyColors()[3]',
|
|
50
|
+
'getTetradicHarmonyColors()[0]',
|
|
51
|
+
'getTetradicHarmonyColors()[1]',
|
|
52
|
+
'getTetradicHarmonyColors()[2]',
|
|
53
|
+
'getTetradicHarmonyColors()[3]',
|
|
54
|
+
'getAnalogousHarmonyColors()[0]',
|
|
55
|
+
'getAnalogousHarmonyColors()[1]',
|
|
56
|
+
'getAnalogousHarmonyColors()[2]',
|
|
57
|
+
'getAnalogousHarmonyColors()[3]',
|
|
58
|
+
'getAnalogousHarmonyColors()[4]',
|
|
59
|
+
'getMonochromaticHarmonyColors()[0]',
|
|
60
|
+
'getMonochromaticHarmonyColors()[1]',
|
|
61
|
+
'getMonochromaticHarmonyColors()[2]',
|
|
62
|
+
'getMonochromaticHarmonyColors()[3]',
|
|
63
|
+
'getMonochromaticHarmonyColors()[4]',
|
|
64
|
+
'getColorSwatch()[300]',
|
|
65
|
+
'getColorSwatch()[400]',
|
|
66
|
+
'getColorSwatch()[600]',
|
|
67
|
+
'getColorSwatch()[700]',
|
|
68
|
+
'getColorPalette()["secondaryColors"][0][500]',
|
|
69
|
+
'getColorPalette()["info"][500]',
|
|
70
|
+
'getColorPalette()["negative"][500]',
|
|
71
|
+
'getColorPalette()["positive"][500]',
|
|
72
|
+
];
|
|
73
|
+
export function getRandomStarterCode() {
|
|
74
|
+
const randomColorHex = Color.random({ paletteSuitable: true }).toHex();
|
|
75
|
+
const updateColorMethod = getRandomElementFromArray(UPDATE_COLOR_METHOD_EXAMPLES);
|
|
76
|
+
const updateColorMethodArgs = updateColorMethod.argOptions
|
|
77
|
+
? getRandomElementFromArray(updateColorMethod.argOptions)
|
|
78
|
+
: undefined;
|
|
79
|
+
const resultColorMethod = getRandomElementFromArray(GET_RESULT_COLOR_EXAMPLES);
|
|
80
|
+
return `// Return a \`Color\` or any valid color format (e.g. a hex string) to see the color visualized
|
|
81
|
+
|
|
82
|
+
const color = new Color("${randomColorHex}");
|
|
83
|
+
console.log("color:", color);
|
|
84
|
+
|
|
85
|
+
const updated = color.${updateColorMethod.method}(${updateColorMethodArgs ?? ''});
|
|
86
|
+
console.log("updated color:", updated);
|
|
87
|
+
|
|
88
|
+
const result = updated.${resultColorMethod};
|
|
89
|
+
return result; // rendered below if valid`;
|
|
90
|
+
}
|
|
91
|
+
function formatMockedJSConsoleValue(value) {
|
|
92
|
+
try {
|
|
93
|
+
if (value === undefined) {
|
|
94
|
+
return 'undefined';
|
|
95
|
+
}
|
|
96
|
+
if (typeof value === 'string') {
|
|
97
|
+
return value;
|
|
98
|
+
}
|
|
99
|
+
if (typeof value === 'function') {
|
|
100
|
+
return `[Function ${value.name || 'anonymous'}]`;
|
|
101
|
+
}
|
|
102
|
+
if (value && typeof value === 'object') {
|
|
103
|
+
// Try to show Color nicely if it has toHexString:
|
|
104
|
+
if ('toHex' in value && typeof value.toHex === 'function') {
|
|
105
|
+
return `Color(${value.toHex()})`;
|
|
106
|
+
}
|
|
107
|
+
return JSON.stringify(value, null, 2);
|
|
108
|
+
}
|
|
109
|
+
return String(value);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return '[unserializable]';
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const ANON_FUNCTION_TRACE_LOCATION_PREFIX = '<anonymous>:';
|
|
116
|
+
const ANON_FUNCTION_LINE_NUMBER_OFFSET = 4; // this is because when we define `codeRunnerFn`, the `${code}` part is on line 5
|
|
117
|
+
function tryToGetLineNumberFromError(error) {
|
|
118
|
+
if (!('stack' in error) || typeof error.stack !== 'string') {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
const { stack } = error;
|
|
122
|
+
const anonFunctionTraceIndex = stack.indexOf(ANON_FUNCTION_TRACE_LOCATION_PREFIX);
|
|
123
|
+
if (anonFunctionTraceIndex < 0) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
const lineNumberPartAndRest = stack.substring(anonFunctionTraceIndex + ANON_FUNCTION_TRACE_LOCATION_PREFIX.length);
|
|
127
|
+
const restIndex = lineNumberPartAndRest.indexOf(':');
|
|
128
|
+
if (restIndex < 0) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
const lineNumberPart = lineNumberPartAndRest.substring(0, restIndex);
|
|
132
|
+
if (!lineNumberPart) {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
const lineNumber = parseInt(lineNumberPart);
|
|
136
|
+
if (isNaN(lineNumber)) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
return lineNumber - ANON_FUNCTION_LINE_NUMBER_OFFSET;
|
|
140
|
+
}
|
|
141
|
+
function getErrorMessage(error, fallbackMessage) {
|
|
142
|
+
if (error && typeof error === 'object') {
|
|
143
|
+
const maybeLineNumber = tryToGetLineNumberFromError(error);
|
|
144
|
+
if ('message' in error && typeof error.message === 'string') {
|
|
145
|
+
return `Error${maybeLineNumber !== null ? ` (line ${maybeLineNumber})` : ''}: ${error.message}`;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return fallbackMessage;
|
|
149
|
+
}
|
|
150
|
+
export var CodeExecutionStatus;
|
|
151
|
+
(function (CodeExecutionStatus) {
|
|
152
|
+
CodeExecutionStatus["CODE_ERROR"] = "CODE_ERROR";
|
|
153
|
+
CodeExecutionStatus["NO_RETURNED_VALUE"] = "NO_RETURNED_VALUE";
|
|
154
|
+
CodeExecutionStatus["INVALID_RETURNED_VALUE"] = "INVALID_RETURNED_VALUE";
|
|
155
|
+
CodeExecutionStatus["SUCCESS"] = "SUCCESS";
|
|
156
|
+
})(CodeExecutionStatus || (CodeExecutionStatus = {}));
|
|
157
|
+
export async function tryToRunCode(code) {
|
|
158
|
+
const capturedJSConsoleOutputs = [];
|
|
159
|
+
const mockJSConsole = {
|
|
160
|
+
log: (...args) => capturedJSConsoleOutputs.push(args.map(formatMockedJSConsoleValue).join(' ')),
|
|
161
|
+
warn: (...args) => capturedJSConsoleOutputs.push('⚠️ ' + args.map(formatMockedJSConsoleValue).join(' ')),
|
|
162
|
+
error: (...args) => capturedJSConsoleOutputs.push('❌ ' + args.map(formatMockedJSConsoleValue).join(' ')),
|
|
163
|
+
};
|
|
164
|
+
let maybeColorValue;
|
|
165
|
+
try {
|
|
166
|
+
const codeRunnerFn = new Function('Color', 'console', `"use strict";
|
|
167
|
+
return (async () => {
|
|
168
|
+
${code}
|
|
169
|
+
})();`);
|
|
170
|
+
maybeColorValue = await codeRunnerFn(Color, mockJSConsole);
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
return {
|
|
174
|
+
consoleOutputs: capturedJSConsoleOutputs,
|
|
175
|
+
errorMessage: getErrorMessage(err, 'Error: invalid code'),
|
|
176
|
+
status: CodeExecutionStatus.CODE_ERROR,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
if (!maybeColorValue) {
|
|
180
|
+
return {
|
|
181
|
+
consoleOutputs: capturedJSConsoleOutputs,
|
|
182
|
+
errorMessage: 'Error: no color returned',
|
|
183
|
+
status: CodeExecutionStatus.NO_RETURNED_VALUE,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
let maybeColor;
|
|
187
|
+
try {
|
|
188
|
+
maybeColor = new Color(maybeColorValue);
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
return {
|
|
192
|
+
consoleOutputs: capturedJSConsoleOutputs,
|
|
193
|
+
errorMessage: getErrorMessage(err, 'Error: invalid returned color value'),
|
|
194
|
+
status: CodeExecutionStatus.INVALID_RETURNED_VALUE,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
color: maybeColor,
|
|
199
|
+
consoleOutputs: capturedJSConsoleOutputs,
|
|
200
|
+
status: CodeExecutionStatus.SUCCESS,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { useEffect, useMemo } from 'react';
|
|
2
|
+
const siteOrigin = 'https://rteammco.github.io';
|
|
3
|
+
const basePath = (import.meta.env.BASE_URL ?? '/').replace(/\/$/, '');
|
|
4
|
+
const withLeadingSlash = (value) => (value.startsWith('/') ? value : `/${value}`);
|
|
5
|
+
const getAbsoluteUrl = (path) => `${siteOrigin}${basePath}${withLeadingSlash(path)}`;
|
|
6
|
+
const resolveImageUrl = (image) => {
|
|
7
|
+
if (!image) {
|
|
8
|
+
return getAbsoluteUrl('/social-card.png');
|
|
9
|
+
}
|
|
10
|
+
if (/^https?:\/\//.test(image)) {
|
|
11
|
+
return image;
|
|
12
|
+
}
|
|
13
|
+
return getAbsoluteUrl(withLeadingSlash(image));
|
|
14
|
+
};
|
|
15
|
+
export function PageHead({ title, description, path, image, type = 'website' }) {
|
|
16
|
+
const canonicalUrl = useMemo(() => getAbsoluteUrl(path), [path]);
|
|
17
|
+
const imageUrl = useMemo(() => resolveImageUrl(image), [image]);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const revertActions = [];
|
|
20
|
+
const updateMeta = (attribute, key, content) => {
|
|
21
|
+
const selector = `meta[${attribute}="${key}"]`;
|
|
22
|
+
let element = document.head.querySelector(selector);
|
|
23
|
+
if (!element) {
|
|
24
|
+
element = document.createElement('meta');
|
|
25
|
+
element.setAttribute(attribute, key);
|
|
26
|
+
document.head.appendChild(element);
|
|
27
|
+
}
|
|
28
|
+
const previousContent = element.getAttribute('content');
|
|
29
|
+
element.setAttribute('content', content);
|
|
30
|
+
revertActions.push(() => {
|
|
31
|
+
if (previousContent === null) {
|
|
32
|
+
element?.remove();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
element?.setAttribute('content', previousContent);
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
const updateCanonical = (href) => {
|
|
39
|
+
let link = document.head.querySelector('link[rel="canonical"]');
|
|
40
|
+
if (!link) {
|
|
41
|
+
link = document.createElement('link');
|
|
42
|
+
link.setAttribute('rel', 'canonical');
|
|
43
|
+
document.head.appendChild(link);
|
|
44
|
+
}
|
|
45
|
+
const previousHref = link.getAttribute('href');
|
|
46
|
+
link.setAttribute('href', href);
|
|
47
|
+
revertActions.push(() => {
|
|
48
|
+
if (previousHref === null) {
|
|
49
|
+
link?.remove();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
link?.setAttribute('href', previousHref);
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
const previousTitle = document.title;
|
|
56
|
+
document.title = title;
|
|
57
|
+
revertActions.push(() => {
|
|
58
|
+
document.title = previousTitle;
|
|
59
|
+
});
|
|
60
|
+
updateCanonical(canonicalUrl);
|
|
61
|
+
updateMeta('name', 'description', description);
|
|
62
|
+
updateMeta('property', 'og:title', title);
|
|
63
|
+
updateMeta('property', 'og:description', description);
|
|
64
|
+
updateMeta('property', 'og:type', type);
|
|
65
|
+
updateMeta('property', 'og:url', canonicalUrl);
|
|
66
|
+
updateMeta('property', 'og:image', imageUrl);
|
|
67
|
+
updateMeta('name', 'twitter:card', 'summary_large_image');
|
|
68
|
+
updateMeta('name', 'twitter:title', title);
|
|
69
|
+
updateMeta('name', 'twitter:description', description);
|
|
70
|
+
updateMeta('name', 'twitter:image', imageUrl);
|
|
71
|
+
return () => {
|
|
72
|
+
revertActions.reverse().forEach((revert) => revert());
|
|
73
|
+
};
|
|
74
|
+
}, [canonicalUrl, description, imageUrl, title, type]);
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
export function StructuredData({ data }) {
|
|
3
|
+
useEffect(() => {
|
|
4
|
+
const script = document.createElement('script');
|
|
5
|
+
script.setAttribute('type', 'application/ld+json');
|
|
6
|
+
script.textContent = JSON.stringify(data);
|
|
7
|
+
document.head.appendChild(script);
|
|
8
|
+
return () => {
|
|
9
|
+
document.head.removeChild(script);
|
|
10
|
+
};
|
|
11
|
+
}, [data]);
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { Icon } from '../components/Icon';
|
|
4
|
+
import { subscribeToToast } from './toastBus';
|
|
5
|
+
const DEFAULT_TOAST_DURATION_MS = 4500;
|
|
6
|
+
function getToastVariantStyles(toastVariant) {
|
|
7
|
+
switch (toastVariant) {
|
|
8
|
+
case 'SUCCESS':
|
|
9
|
+
return {
|
|
10
|
+
iconClassName: 'text-emerald-600 dark:text-emerald-300',
|
|
11
|
+
iconType: Icon.TYPE.CHECK_CIRCLE,
|
|
12
|
+
};
|
|
13
|
+
case 'ERROR':
|
|
14
|
+
return {
|
|
15
|
+
iconClassName: 'text-rose-600 dark:text-rose-300',
|
|
16
|
+
iconType: Icon.TYPE.X_CIRCLE,
|
|
17
|
+
};
|
|
18
|
+
case 'INFO':
|
|
19
|
+
default:
|
|
20
|
+
return {
|
|
21
|
+
iconClassName: 'text-blue-600 dark:text-blue-300',
|
|
22
|
+
iconType: Icon.TYPE.INFO_CIRCLE,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function ToastProvider({ children }) {
|
|
27
|
+
const [toasts, setToasts] = useState([]);
|
|
28
|
+
const dismissTimeoutMapRef = useRef(new Map());
|
|
29
|
+
const dismissToast = useCallback((toastID) => {
|
|
30
|
+
const dismissTimeout = dismissTimeoutMapRef.current.get(toastID);
|
|
31
|
+
if (dismissTimeout != null) {
|
|
32
|
+
window.clearTimeout(dismissTimeout);
|
|
33
|
+
dismissTimeoutMapRef.current.delete(toastID);
|
|
34
|
+
}
|
|
35
|
+
setToasts((currentToasts) => currentToasts.filter((currentToast) => currentToast.id !== toastID));
|
|
36
|
+
}, []);
|
|
37
|
+
const enqueueToast = useCallback((toastEvent) => {
|
|
38
|
+
const toastID = `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
39
|
+
const toastDurationMs = toastEvent.durationMs == null ? DEFAULT_TOAST_DURATION_MS : toastEvent.durationMs;
|
|
40
|
+
setToasts((currentToasts) => [...currentToasts, { ...toastEvent, id: toastID }]);
|
|
41
|
+
if (toastDurationMs > 0) {
|
|
42
|
+
const dismissTimeout = window.setTimeout(() => {
|
|
43
|
+
dismissToast(toastID);
|
|
44
|
+
}, toastDurationMs);
|
|
45
|
+
dismissTimeoutMapRef.current.set(toastID, dismissTimeout);
|
|
46
|
+
}
|
|
47
|
+
}, [dismissToast]);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
const dismissTimeoutMap = dismissTimeoutMapRef.current;
|
|
50
|
+
return () => {
|
|
51
|
+
dismissTimeoutMap.forEach((dismissTimeout) => {
|
|
52
|
+
window.clearTimeout(dismissTimeout);
|
|
53
|
+
});
|
|
54
|
+
dismissTimeoutMap.clear();
|
|
55
|
+
};
|
|
56
|
+
}, []);
|
|
57
|
+
useEffect(() => subscribeToToast(enqueueToast), [enqueueToast]);
|
|
58
|
+
return (_jsxs(_Fragment, { children: [children, _jsx("div", { className: "pointer-events-none fixed right-4 bottom-4 z-50 flex max-w-sm flex-col gap-2", children: toasts.map((toast) => {
|
|
59
|
+
const variantStyles = getToastVariantStyles(toast.variant);
|
|
60
|
+
return (_jsx("div", { "aria-atomic": "true", className: "pointer-events-auto rounded-xl border border-slate-200 bg-white/95 p-3 text-left shadow-lg backdrop-blur-sm dark:border-slate-700 dark:bg-slate-900/95", role: toast.variant === 'ERROR' ? 'alert' : 'status', children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { className: variantStyles.iconClassName, children: _jsx(Icon, { size: 20, type: variantStyles.iconType }) }), _jsxs("div", { className: "flex-1 text-sm text-slate-800 dark:text-slate-100", children: [_jsx("p", { className: "font-medium", children: toast.message }), toast.description != null ? (_jsx("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: toast.description })) : null] }), _jsx("button", { "aria-label": "Dismiss alert", className: "icon-button", onClick: () => dismissToast(toast.id), type: "button", children: _jsx(Icon, { size: 18, type: Icon.TYPE.X }) })] }) }, toast.id));
|
|
61
|
+
}) })] }));
|
|
62
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type ToastVariant = 'SUCCESS' | 'ERROR' | 'INFO';
|
|
2
|
+
export interface ToastEvent {
|
|
3
|
+
description?: string;
|
|
4
|
+
durationMs?: number;
|
|
5
|
+
message: string;
|
|
6
|
+
variant: ToastVariant;
|
|
7
|
+
}
|
|
8
|
+
type ToastListener = (toastEvent: ToastEvent) => void;
|
|
9
|
+
export declare function subscribeToToast(listener: ToastListener): () => void;
|
|
10
|
+
export declare function showSuccessToast(message: string, durationMs?: number): void;
|
|
11
|
+
export declare function showInfoToast(message: string, durationMs?: number): void;
|
|
12
|
+
export declare function showErrorToast(message: string, error?: unknown, durationMs?: number): void;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const toastListeners = new Set();
|
|
2
|
+
export function subscribeToToast(listener) {
|
|
3
|
+
toastListeners.add(listener);
|
|
4
|
+
return () => {
|
|
5
|
+
toastListeners.delete(listener);
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
function showToast(toastEvent) {
|
|
9
|
+
toastListeners.forEach((listener) => {
|
|
10
|
+
listener(toastEvent);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
export function showSuccessToast(message, durationMs) {
|
|
14
|
+
showToast({ durationMs, message, variant: 'SUCCESS' });
|
|
15
|
+
}
|
|
16
|
+
export function showInfoToast(message, durationMs) {
|
|
17
|
+
showToast({ durationMs, message, variant: 'INFO' });
|
|
18
|
+
}
|
|
19
|
+
export function showErrorToast(message, error, durationMs) {
|
|
20
|
+
const errorDescription = error instanceof Error ? error.message : error != null ? String(error) : undefined;
|
|
21
|
+
showToast({
|
|
22
|
+
description: errorDescription,
|
|
23
|
+
durationMs,
|
|
24
|
+
message,
|
|
25
|
+
variant: 'ERROR',
|
|
26
|
+
});
|
|
27
|
+
}
|