@prestack/thread-ui 0.0.1
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/CHANGELOG.md +348 -0
- package/dist/attach.d.ts +1 -0
- package/dist/attach.js +1 -0
- package/dist/ui/animations/anm_appear.d.ts +16 -0
- package/dist/ui/animations/anm_appear.js +10 -0
- package/dist/ui/animations/anm_blur_in.d.ts +22 -0
- package/dist/ui/animations/anm_blur_in.js +16 -0
- package/dist/ui/animations/anm_blur_out.d.ts +22 -0
- package/dist/ui/animations/anm_blur_out.js +16 -0
- package/dist/ui/animations/anm_dismiss.d.ts +22 -0
- package/dist/ui/animations/anm_dismiss.js +16 -0
- package/dist/ui/animations/anm_drop.d.ts +22 -0
- package/dist/ui/animations/anm_drop.js +16 -0
- package/dist/ui/animations/anm_fall.d.ts +22 -0
- package/dist/ui/animations/anm_fall.js +16 -0
- package/dist/ui/animations/anm_flash.d.ts +19 -0
- package/dist/ui/animations/anm_flash.js +16 -0
- package/dist/ui/animations/anm_glow.d.ts +16 -0
- package/dist/ui/animations/anm_glow.js +14 -0
- package/dist/ui/animations/anm_lift.d.ts +16 -0
- package/dist/ui/animations/anm_lift.js +14 -0
- package/dist/ui/animations/anm_nudge.d.ts +16 -0
- package/dist/ui/animations/anm_nudge.js +14 -0
- package/dist/ui/animations/anm_pop_in.d.ts +29 -0
- package/dist/ui/animations/anm_pop_in.js +20 -0
- package/dist/ui/animations/anm_pop_out.d.ts +29 -0
- package/dist/ui/animations/anm_pop_out.js +20 -0
- package/dist/ui/animations/anm_press.d.ts +19 -0
- package/dist/ui/animations/anm_press.js +10 -0
- package/dist/ui/animations/anm_pulse.d.ts +20 -0
- package/dist/ui/animations/anm_pulse.js +11 -0
- package/dist/ui/animations/anm_rise.d.ts +22 -0
- package/dist/ui/animations/anm_rise.js +16 -0
- package/dist/ui/animations/anm_shake.d.ts +23 -0
- package/dist/ui/animations/anm_shake.js +11 -0
- package/dist/ui/animations/anm_slide_in_left.d.ts +22 -0
- package/dist/ui/animations/anm_slide_in_left.js +16 -0
- package/dist/ui/animations/anm_slide_in_right.d.ts +22 -0
- package/dist/ui/animations/anm_slide_in_right.js +16 -0
- package/dist/ui/animations/anm_slide_out_left.d.ts +22 -0
- package/dist/ui/animations/anm_slide_out_left.js +16 -0
- package/dist/ui/animations/anm_slide_out_right.d.ts +22 -0
- package/dist/ui/animations/anm_slide_out_right.js +16 -0
- package/dist/ui/animations/anm_spin.d.ts +16 -0
- package/dist/ui/animations/anm_spin.js +10 -0
- package/dist/ui/animations/anm_swell.d.ts +16 -0
- package/dist/ui/animations/anm_swell.js +14 -0
- package/dist/ui/animations/anm_wobble.d.ts +27 -0
- package/dist/ui/animations/anm_wobble.js +22 -0
- package/dist/ui/animations/anm_zoom_in.d.ts +22 -0
- package/dist/ui/animations/anm_zoom_in.js +16 -0
- package/dist/ui/animations/anm_zoom_out.d.ts +22 -0
- package/dist/ui/animations/anm_zoom_out.js +16 -0
- package/dist/ui/animations.d.ts +59 -0
- package/dist/ui/animations.js +227 -0
- package/dist/ui/attach.d.ts +3 -0
- package/dist/ui/attach.js +497 -0
- package/dist/ui/charts.d.ts +32 -0
- package/dist/ui/charts.js +35 -0
- package/dist/ui/checked.d.ts +19 -0
- package/dist/ui/checked.js +3 -0
- package/dist/ui/collector.d.ts +32 -0
- package/dist/ui/collector.js +75 -0
- package/dist/ui/compositions.d.ts +21 -0
- package/dist/ui/compositions.js +305 -0
- package/dist/ui/consent.d.ts +22 -0
- package/dist/ui/consent.js +44 -0
- package/dist/ui/content.d.ts +9 -0
- package/dist/ui/content.js +11 -0
- package/dist/ui/contrast.d.ts +3 -0
- package/dist/ui/contrast.js +23 -0
- package/dist/ui/controls.d.ts +14 -0
- package/dist/ui/controls.js +2 -0
- package/dist/ui/disclosure.d.ts +14 -0
- package/dist/ui/disclosure.js +2 -0
- package/dist/ui/dismiss-layer.d.ts +14 -0
- package/dist/ui/dismiss-layer.js +66 -0
- package/dist/ui/door.d.ts +40 -0
- package/dist/ui/door.js +100 -0
- package/dist/ui/drag.d.ts +82 -0
- package/dist/ui/drag.js +212 -0
- package/dist/ui/elements/accordion.d.ts +12 -0
- package/dist/ui/elements/accordion.js +16 -0
- package/dist/ui/elements/accordion.works.d.ts +22 -0
- package/dist/ui/elements/accordion.works.js +44 -0
- package/dist/ui/elements/aspect-ratio.d.ts +10 -0
- package/dist/ui/elements/aspect-ratio.js +9 -0
- package/dist/ui/elements/aspect-ratio.works.d.ts +2 -0
- package/dist/ui/elements/aspect-ratio.works.js +3 -0
- package/dist/ui/elements/avatar.d.ts +11 -0
- package/dist/ui/elements/avatar.js +10 -0
- package/dist/ui/elements/avatar.works.d.ts +4 -0
- package/dist/ui/elements/avatar.works.js +16 -0
- package/dist/ui/elements/badge.d.ts +11 -0
- package/dist/ui/elements/badge.js +10 -0
- package/dist/ui/elements/badge.works.d.ts +5 -0
- package/dist/ui/elements/badge.works.js +6 -0
- package/dist/ui/elements/bars.d.ts +14 -0
- package/dist/ui/elements/bars.js +17 -0
- package/dist/ui/elements/bars.works.d.ts +12 -0
- package/dist/ui/elements/bars.works.js +20 -0
- package/dist/ui/elements/box.d.ts +12 -0
- package/dist/ui/elements/box.js +11 -0
- package/dist/ui/elements/breadcrumb.d.ts +10 -0
- package/dist/ui/elements/breadcrumb.js +12 -0
- package/dist/ui/elements/breadcrumb.works.d.ts +7 -0
- package/dist/ui/elements/breadcrumb.works.js +21 -0
- package/dist/ui/elements/button.d.ts +17 -0
- package/dist/ui/elements/button.js +16 -0
- package/dist/ui/elements/button.works.d.ts +17 -0
- package/dist/ui/elements/button.works.js +34 -0
- package/dist/ui/elements/column.d.ts +9 -0
- package/dist/ui/elements/column.js +8 -0
- package/dist/ui/elements/consent.d.ts +13 -0
- package/dist/ui/elements/consent.js +21 -0
- package/dist/ui/elements/consent.works.d.ts +41 -0
- package/dist/ui/elements/consent.works.js +79 -0
- package/dist/ui/elements/donut.d.ts +13 -0
- package/dist/ui/elements/donut.js +16 -0
- package/dist/ui/elements/donut.works.d.ts +11 -0
- package/dist/ui/elements/donut.works.js +28 -0
- package/dist/ui/elements/each.d.ts +14 -0
- package/dist/ui/elements/each.js +9 -0
- package/dist/ui/elements/each.works.d.ts +3 -0
- package/dist/ui/elements/each.works.js +68 -0
- package/dist/ui/elements/empty.d.ts +9 -0
- package/dist/ui/elements/empty.js +12 -0
- package/dist/ui/elements/field.d.ts +16 -0
- package/dist/ui/elements/field.js +15 -0
- package/dist/ui/elements/field.works.d.ts +17 -0
- package/dist/ui/elements/field.works.js +45 -0
- package/dist/ui/elements/funnel.d.ts +14 -0
- package/dist/ui/elements/funnel.js +17 -0
- package/dist/ui/elements/funnel.works.d.ts +12 -0
- package/dist/ui/elements/funnel.works.js +23 -0
- package/dist/ui/elements/gauge.d.ts +12 -0
- package/dist/ui/elements/gauge.js +15 -0
- package/dist/ui/elements/gauge.works.d.ts +11 -0
- package/dist/ui/elements/gauge.works.js +31 -0
- package/dist/ui/elements/glyph.d.ts +10 -0
- package/dist/ui/elements/glyph.js +9 -0
- package/dist/ui/elements/glyph.works.d.ts +5 -0
- package/dist/ui/elements/glyph.works.js +16 -0
- package/dist/ui/elements/grid.d.ts +9 -0
- package/dist/ui/elements/grid.js +8 -0
- package/dist/ui/elements/heatmap.d.ts +15 -0
- package/dist/ui/elements/heatmap.js +17 -0
- package/dist/ui/elements/heatmap.works.d.ts +11 -0
- package/dist/ui/elements/heatmap.works.js +11 -0
- package/dist/ui/elements/hit-box.d.ts +19 -0
- package/dist/ui/elements/hit-box.js +15 -0
- package/dist/ui/elements/hit-box.works.d.ts +87 -0
- package/dist/ui/elements/hit-box.works.js +451 -0
- package/dist/ui/elements/image.d.ts +10 -0
- package/dist/ui/elements/image.js +9 -0
- package/dist/ui/elements/line-chart.d.ts +13 -0
- package/dist/ui/elements/line-chart.js +16 -0
- package/dist/ui/elements/line-chart.works.d.ts +12 -0
- package/dist/ui/elements/line-chart.works.js +27 -0
- package/dist/ui/elements/link.d.ts +12 -0
- package/dist/ui/elements/link.js +15 -0
- package/dist/ui/elements/link.works.d.ts +10 -0
- package/dist/ui/elements/link.works.js +15 -0
- package/dist/ui/elements/media.d.ts +11 -0
- package/dist/ui/elements/media.js +22 -0
- package/dist/ui/elements/menu.d.ts +12 -0
- package/dist/ui/elements/menu.js +18 -0
- package/dist/ui/elements/menu.works.d.ts +50 -0
- package/dist/ui/elements/menu.works.js +100 -0
- package/dist/ui/elements/money.d.ts +10 -0
- package/dist/ui/elements/money.js +9 -0
- package/dist/ui/elements/money.works.d.ts +4 -0
- package/dist/ui/elements/money.works.js +4 -0
- package/dist/ui/elements/pagination.d.ts +11 -0
- package/dist/ui/elements/pagination.js +12 -0
- package/dist/ui/elements/pagination.works.d.ts +5 -0
- package/dist/ui/elements/pagination.works.js +15 -0
- package/dist/ui/elements/progress.d.ts +11 -0
- package/dist/ui/elements/progress.js +11 -0
- package/dist/ui/elements/progress.works.d.ts +2 -0
- package/dist/ui/elements/progress.works.js +6 -0
- package/dist/ui/elements/radio-group.d.ts +15 -0
- package/dist/ui/elements/radio-group.js +16 -0
- package/dist/ui/elements/radio-group.works.d.ts +10 -0
- package/dist/ui/elements/radio-group.works.js +22 -0
- package/dist/ui/elements/row.d.ts +9 -0
- package/dist/ui/elements/row.js +8 -0
- package/dist/ui/elements/scatter.d.ts +13 -0
- package/dist/ui/elements/scatter.js +15 -0
- package/dist/ui/elements/scatter.works.d.ts +11 -0
- package/dist/ui/elements/scatter.works.js +24 -0
- package/dist/ui/elements/select.d.ts +13 -0
- package/dist/ui/elements/select.js +11 -0
- package/dist/ui/elements/select.works.d.ts +4 -0
- package/dist/ui/elements/select.works.js +3 -0
- package/dist/ui/elements/separator.d.ts +10 -0
- package/dist/ui/elements/separator.js +9 -0
- package/dist/ui/elements/skeleton.d.ts +8 -0
- package/dist/ui/elements/skeleton.js +9 -0
- package/dist/ui/elements/slider.d.ts +14 -0
- package/dist/ui/elements/slider.js +10 -0
- package/dist/ui/elements/slider.works.d.ts +4 -0
- package/dist/ui/elements/slider.works.js +3 -0
- package/dist/ui/elements/sparkline.d.ts +10 -0
- package/dist/ui/elements/sparkline.js +15 -0
- package/dist/ui/elements/sparkline.works.d.ts +10 -0
- package/dist/ui/elements/sparkline.works.js +19 -0
- package/dist/ui/elements/spinner.d.ts +9 -0
- package/dist/ui/elements/spinner.js +12 -0
- package/dist/ui/elements/stack.d.ts +9 -0
- package/dist/ui/elements/stack.js +8 -0
- package/dist/ui/elements/stat.d.ts +12 -0
- package/dist/ui/elements/stat.js +10 -0
- package/dist/ui/elements/stat.works.d.ts +3 -0
- package/dist/ui/elements/stat.works.js +10 -0
- package/dist/ui/elements/surface.d.ts +9 -0
- package/dist/ui/elements/surface.js +15 -0
- package/dist/ui/elements/surface.works.d.ts +7 -0
- package/dist/ui/elements/surface.works.js +4 -0
- package/dist/ui/elements/table.d.ts +13 -0
- package/dist/ui/elements/table.js +16 -0
- package/dist/ui/elements/table.works.d.ts +11 -0
- package/dist/ui/elements/table.works.js +15 -0
- package/dist/ui/elements/tabs.d.ts +12 -0
- package/dist/ui/elements/tabs.js +16 -0
- package/dist/ui/elements/tabs.works.d.ts +25 -0
- package/dist/ui/elements/tabs.works.js +53 -0
- package/dist/ui/elements/text.d.ts +13 -0
- package/dist/ui/elements/text.js +9 -0
- package/dist/ui/elements/textarea.d.ts +14 -0
- package/dist/ui/elements/textarea.js +11 -0
- package/dist/ui/elements/textarea.works.d.ts +4 -0
- package/dist/ui/elements/textarea.works.js +3 -0
- package/dist/ui/elements/time.d.ts +11 -0
- package/dist/ui/elements/time.js +14 -0
- package/dist/ui/elements/time.works.d.ts +11 -0
- package/dist/ui/elements/time.works.js +16 -0
- package/dist/ui/elements/toggle.d.ts +11 -0
- package/dist/ui/elements/toggle.js +10 -0
- package/dist/ui/elements/toggle.works.d.ts +4 -0
- package/dist/ui/elements/toggle.works.js +3 -0
- package/dist/ui/elements/tooltip.d.ts +12 -0
- package/dist/ui/elements/tooltip.js +15 -0
- package/dist/ui/elements/tooltip.works.d.ts +28 -0
- package/dist/ui/elements/tooltip.works.js +54 -0
- package/dist/ui/elements/value.d.ts +12 -0
- package/dist/ui/elements/value.js +9 -0
- package/dist/ui/elements/value.works.d.ts +4 -0
- package/dist/ui/elements/value.works.js +4 -0
- package/dist/ui/elements.d.ts +1143 -0
- package/dist/ui/elements.js +68 -0
- package/dist/ui/focus-scope.d.ts +7 -0
- package/dist/ui/focus-scope.js +109 -0
- package/dist/ui/fonts.d.ts +103 -0
- package/dist/ui/fonts.js +243 -0
- package/dist/ui/generators/dev.d.ts +2 -0
- package/dist/ui/generators/dev.js +61 -0
- package/dist/ui/generators/elements.d.ts +31 -0
- package/dist/ui/generators/elements.js +520 -0
- package/dist/ui/generators/i18n.d.ts +5 -0
- package/dist/ui/generators/i18n.js +264 -0
- package/dist/ui/generators/icons.d.ts +1 -0
- package/dist/ui/generators/icons.js +187 -0
- package/dist/ui/generators/react.d.ts +26 -0
- package/dist/ui/generators/react.js +218 -0
- package/dist/ui/generators/routes.d.ts +11 -0
- package/dist/ui/generators/routes.js +597 -0
- package/dist/ui/generators/show.d.ts +1 -0
- package/dist/ui/generators/show.js +231 -0
- package/dist/ui/generators/styles.d.ts +1 -0
- package/dist/ui/generators/styles.js +502 -0
- package/dist/ui/generators/variants.d.ts +12 -0
- package/dist/ui/generators/variants.js +162 -0
- package/dist/ui/i18n/catalogs/en.d.ts +172 -0
- package/dist/ui/i18n/catalogs/en.js +148 -0
- package/dist/ui/i18n/format.d.ts +13 -0
- package/dist/ui/i18n/format.js +161 -0
- package/dist/ui/i18n/locales.d.ts +9 -0
- package/dist/ui/i18n/locales.js +20 -0
- package/dist/ui/i18n/parse.d.ts +45 -0
- package/dist/ui/i18n/parse.js +249 -0
- package/dist/ui/i18n/translator.d.ts +10 -0
- package/dist/ui/i18n/translator.js +22 -0
- package/dist/ui/i18n/types.d.ts +33 -0
- package/dist/ui/i18n/types.js +9 -0
- package/dist/ui/icons.d.ts +67 -0
- package/dist/ui/icons.js +249 -0
- package/dist/ui/islands/map.d.ts +33 -0
- package/dist/ui/islands/map.js +44 -0
- package/dist/ui/localizations.d.ts +33 -0
- package/dist/ui/localizations.js +51 -0
- package/dist/ui/makers/message.d.ts +1 -0
- package/dist/ui/makers/message.js +230 -0
- package/dist/ui/material.d.ts +83 -0
- package/dist/ui/material.js +95 -0
- package/dist/ui/materials/mat_bordered.d.ts +22 -0
- package/dist/ui/materials/mat_bordered.js +12 -0
- package/dist/ui/materials/mat_ceramic.d.ts +22 -0
- package/dist/ui/materials/mat_ceramic.js +12 -0
- package/dist/ui/materials/mat_clay.d.ts +22 -0
- package/dist/ui/materials/mat_clay.js +12 -0
- package/dist/ui/materials/mat_elevated.d.ts +32 -0
- package/dist/ui/materials/mat_elevated.js +23 -0
- package/dist/ui/materials/mat_flat.d.ts +50 -0
- package/dist/ui/materials/mat_flat.js +33 -0
- package/dist/ui/materials/mat_glass.d.ts +32 -0
- package/dist/ui/materials/mat_glass.js +19 -0
- package/dist/ui/materials/mat_lit.d.ts +22 -0
- package/dist/ui/materials/mat_lit.js +12 -0
- package/dist/ui/materials/mat_moulded.d.ts +16 -0
- package/dist/ui/materials/mat_moulded.js +10 -0
- package/dist/ui/materials.d.ts +56 -0
- package/dist/ui/materials.js +175 -0
- package/dist/ui/modes.d.ts +25 -0
- package/dist/ui/modes.js +25 -0
- package/dist/ui/navigation.d.ts +3 -0
- package/dist/ui/navigation.js +24 -0
- package/dist/ui/positioning.d.ts +24 -0
- package/dist/ui/positioning.js +48 -0
- package/dist/ui/presented.d.ts +10 -0
- package/dist/ui/presented.js +81 -0
- package/dist/ui/provider.d.ts +31 -0
- package/dist/ui/provider.js +104 -0
- package/dist/ui/render-loop.d.ts +12 -0
- package/dist/ui/render-loop.js +94 -0
- package/dist/ui/roving-focus.d.ts +15 -0
- package/dist/ui/roving-focus.js +143 -0
- package/dist/ui/screens.d.ts +17 -0
- package/dist/ui/screens.js +112 -0
- package/dist/ui/scroll-lock.d.ts +2 -0
- package/dist/ui/scroll-lock.js +24 -0
- package/dist/ui/series.d.ts +9 -0
- package/dist/ui/series.js +67 -0
- package/dist/ui/signals.d.ts +120 -0
- package/dist/ui/signals.js +286 -0
- package/dist/ui/styleguide.d.ts +27 -0
- package/dist/ui/styleguide.js +138 -0
- package/dist/ui/styleguides.d.ts +11 -0
- package/dist/ui/styleguides.js +299 -0
- package/dist/ui/themes.d.ts +5 -0
- package/dist/ui/themes.js +16 -0
- package/dist/ui/token.d.ts +16 -0
- package/dist/ui/token.js +37 -0
- package/dist/ui/tokens/shadow.d.ts +6 -0
- package/dist/ui/tokens/shadow.js +17 -0
- package/dist/ui/tokens.d.ts +180 -0
- package/dist/ui/tokens.js +200 -0
- package/dist/ui/validators.d.ts +37 -0
- package/dist/ui/validators.js +184 -0
- package/dist/ui/variant.d.ts +122 -0
- package/dist/ui/variant.js +201 -0
- package/dist/ui/variants/var_avatar-round.d.ts +23 -0
- package/dist/ui/variants/var_avatar-round.js +13 -0
- package/dist/ui/variants/var_bubble-me.d.ts +21 -0
- package/dist/ui/variants/var_bubble-me.js +13 -0
- package/dist/ui/variants/var_bubble-them.d.ts +18 -0
- package/dist/ui/variants/var_bubble-them.js +12 -0
- package/dist/ui/variants/var_button-border.d.ts +116 -0
- package/dist/ui/variants/var_button-border.js +75 -0
- package/dist/ui/variants/var_button-cta.d.ts +116 -0
- package/dist/ui/variants/var_button-cta.js +75 -0
- package/dist/ui/variants/var_button-destructive-ghost.d.ts +113 -0
- package/dist/ui/variants/var_button-destructive-ghost.js +71 -0
- package/dist/ui/variants/var_button-destructive.d.ts +116 -0
- package/dist/ui/variants/var_button-destructive.js +75 -0
- package/dist/ui/variants/var_button-fill.d.ts +116 -0
- package/dist/ui/variants/var_button-fill.js +75 -0
- package/dist/ui/variants/var_button-ghost.d.ts +113 -0
- package/dist/ui/variants/var_button-ghost.js +71 -0
- package/dist/ui/variants/var_button-glass.d.ts +84 -0
- package/dist/ui/variants/var_button-glass.js +54 -0
- package/dist/ui/variants/var_button-normal.d.ts +116 -0
- package/dist/ui/variants/var_button-normal.js +75 -0
- package/dist/ui/variants/var_button-quiet.d.ts +119 -0
- package/dist/ui/variants/var_button-quiet.js +73 -0
- package/dist/ui/variants/var_card.d.ts +30 -0
- package/dist/ui/variants/var_card.js +16 -0
- package/dist/ui/variants/var_chip.d.ts +18 -0
- package/dist/ui/variants/var_chip.js +12 -0
- package/dist/ui/variants/var_choice.d.ts +26 -0
- package/dist/ui/variants/var_choice.js +14 -0
- package/dist/ui/variants/var_framed.d.ts +11 -0
- package/dist/ui/variants/var_framed.js +9 -0
- package/dist/ui/variants/var_glyph-plain.d.ts +14 -0
- package/dist/ui/variants/var_glyph-plain.js +10 -0
- package/dist/ui/variants/var_input.d.ts +61 -0
- package/dist/ui/variants/var_input.js +42 -0
- package/dist/ui/variants/var_link-inline.d.ts +39 -0
- package/dist/ui/variants/var_link-inline.js +28 -0
- package/dist/ui/variants/var_list-row.d.ts +47 -0
- package/dist/ui/variants/var_list-row.js +33 -0
- package/dist/ui/variants/var_rule.d.ts +11 -0
- package/dist/ui/variants/var_rule.js +9 -0
- package/dist/ui/variants/var_skeleton-block.d.ts +17 -0
- package/dist/ui/variants/var_skeleton-block.js +11 -0
- package/dist/ui/variants/var_spinner-turning.d.ts +17 -0
- package/dist/ui/variants/var_spinner-turning.js +11 -0
- package/dist/ui/variants/var_stat-tile.d.ts +18 -0
- package/dist/ui/variants/var_stat-tile.js +12 -0
- package/dist/ui/variants/var_tab-bar.d.ts +24 -0
- package/dist/ui/variants/var_tab-bar.js +14 -0
- package/dist/ui/variants/var_tap-target.d.ts +33 -0
- package/dist/ui/variants/var_tap-target.js +24 -0
- package/dist/ui/variants.d.ts +174 -0
- package/dist/ui/variants.js +50 -0
- package/dist/ui/wrappers.d.ts +128 -0
- package/dist/ui/wrappers.js +220 -0
- package/package.json +16 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const ViewId: z.ZodString;
|
|
3
|
+
export declare const ScreenName: z.ZodString;
|
|
4
|
+
export declare const ScreenSchema: z.ZodObject<{
|
|
5
|
+
id: z.ZodString;
|
|
6
|
+
nameKey: z.ZodString;
|
|
7
|
+
path: z.ZodOptional<z.ZodString>;
|
|
8
|
+
entry: z.ZodDefault<z.ZodBoolean>;
|
|
9
|
+
shows: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
10
|
+
}, z.core.$strict>;
|
|
11
|
+
export type Screen = z.infer<typeof ScreenSchema>;
|
|
12
|
+
export declare const LinkSchema: z.ZodObject<{
|
|
13
|
+
from: z.ZodString;
|
|
14
|
+
to: z.ZodString;
|
|
15
|
+
labelKey: z.ZodOptional<z.ZodString>;
|
|
16
|
+
}, z.core.$strict>;
|
|
17
|
+
export type Link = z.infer<typeof LinkSchema>;
|
|
18
|
+
export declare const MapSchema: z.ZodObject<{
|
|
19
|
+
specVersion: z.ZodLiteral<1>;
|
|
20
|
+
screens: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
21
|
+
id: z.ZodString;
|
|
22
|
+
nameKey: z.ZodString;
|
|
23
|
+
path: z.ZodOptional<z.ZodString>;
|
|
24
|
+
entry: z.ZodDefault<z.ZodBoolean>;
|
|
25
|
+
shows: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
26
|
+
}, z.core.$strict>>>;
|
|
27
|
+
links: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
28
|
+
from: z.ZodString;
|
|
29
|
+
to: z.ZodString;
|
|
30
|
+
labelKey: z.ZodOptional<z.ZodString>;
|
|
31
|
+
}, z.core.$strict>>>;
|
|
32
|
+
}, z.core.$strict>;
|
|
33
|
+
export type MapIsland = z.infer<typeof MapSchema>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const ElementName = z
|
|
3
|
+
.string()
|
|
4
|
+
.regex(/^[A-Z][A-Za-z0-9]*$/, 'must be a component name, e.g. "Card"')
|
|
5
|
+
.describe('The export name. A screen is reached by importing it, so this is its address.');
|
|
6
|
+
export const ViewId = z
|
|
7
|
+
.string()
|
|
8
|
+
.regex(/^vw_[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/, 'Expected a view id ("vw_" + snake_case)')
|
|
9
|
+
.describe('The id of a declared read. A screen names one; it never states what the read does.');
|
|
10
|
+
export const ScreenName = ElementName.describe('The screen’s export name — `Home`, `Pricing`, `SignIn`. What `navigateTo` names, and its whole address.');
|
|
11
|
+
export const ScreenSchema = z
|
|
12
|
+
.strictObject({
|
|
13
|
+
id: ScreenName,
|
|
14
|
+
nameKey: z
|
|
15
|
+
.string()
|
|
16
|
+
.min(1)
|
|
17
|
+
.describe('The i18n key naming this screen — in a breadcrumb, a tab, a title. Never prose (rule: every user-facing string is a key).'),
|
|
18
|
+
path: z
|
|
19
|
+
.string()
|
|
20
|
+
.regex(/^\/(?:[a-z0-9-]+|\[[a-z][a-zA-Z0-9]*\])(?:\/(?:[a-z0-9-]+|\[[a-z][a-zA-Z0-9]*\]))*$|^\/$/, 'must be an App Router path, e.g. "/campaign/[id]"')
|
|
21
|
+
.optional()
|
|
22
|
+
.describe('Where this screen lives. `/`, `/settings`, `/campaign/[id]`. Absent for a sheet, popover, overlay or toast, which a press opens where somebody already is, so it has no address of its own.'),
|
|
23
|
+
entry: z.boolean().default(false).describe('True when somebody can arrive here without following a link from inside the app.'),
|
|
24
|
+
shows: z.array(ViewId).default([]).describe('Declared views this screen binds to. A screen binds; it never fetches.'),
|
|
25
|
+
})
|
|
26
|
+
.describe('One screen: where it lives, what it rests on, and whether somebody can arrive at it directly.');
|
|
27
|
+
export const LinkSchema = z
|
|
28
|
+
.strictObject({
|
|
29
|
+
from: ScreenName.describe('The screen somebody is on.'),
|
|
30
|
+
to: ScreenName.describe('The screen they arrive at.'),
|
|
31
|
+
labelKey: z
|
|
32
|
+
.string()
|
|
33
|
+
.min(1)
|
|
34
|
+
.optional()
|
|
35
|
+
.describe('The i18n key of the button or link somebody presses to get there. Read off the press itself, and absent only when the press carries no wording.'),
|
|
36
|
+
})
|
|
37
|
+
.describe('One edge: somebody on `from` can reach `to`.');
|
|
38
|
+
export const MapSchema = z
|
|
39
|
+
.strictObject({
|
|
40
|
+
specVersion: z.literal(1),
|
|
41
|
+
screens: z.array(ScreenSchema).default([]),
|
|
42
|
+
links: z.array(LinkSchema).default([]),
|
|
43
|
+
})
|
|
44
|
+
.describe('The map: the screens an app has and how somebody moves between them.');
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Threaded } from '@prestack/thread/core/thread';
|
|
2
|
+
type Row = Omit<Threaded, 'at'> & {
|
|
3
|
+
readonly section?: string;
|
|
4
|
+
readonly is?: string;
|
|
5
|
+
readonly sets?: Readonly<Record<string, string>>;
|
|
6
|
+
};
|
|
7
|
+
export declare function fileFor(language: string): string;
|
|
8
|
+
export declare const SOURCE_ROW = "source";
|
|
9
|
+
export declare const holds: readonly Row[];
|
|
10
|
+
export declare const declares: readonly (Row & {
|
|
11
|
+
readonly at: string;
|
|
12
|
+
})[];
|
|
13
|
+
export declare const LOCALIZATIONS: Threaded & {
|
|
14
|
+
readonly files: string;
|
|
15
|
+
readonly holds: readonly Row[];
|
|
16
|
+
readonly declares: readonly (Row & {
|
|
17
|
+
readonly at: string;
|
|
18
|
+
})[];
|
|
19
|
+
};
|
|
20
|
+
export declare function languagesIn(rows: readonly {
|
|
21
|
+
readonly id: string;
|
|
22
|
+
readonly is?: string;
|
|
23
|
+
readonly sets?: Readonly<Record<string, string>>;
|
|
24
|
+
}[]): readonly {
|
|
25
|
+
readonly id: string;
|
|
26
|
+
readonly name: string;
|
|
27
|
+
readonly flag: string;
|
|
28
|
+
}[];
|
|
29
|
+
export declare function sourceIn(rows: readonly {
|
|
30
|
+
readonly id: string;
|
|
31
|
+
readonly is?: string;
|
|
32
|
+
}[]): string | undefined;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export function fileFor(language) {
|
|
2
|
+
return `i18n/${language}.json`;
|
|
3
|
+
}
|
|
4
|
+
export const SOURCE_ROW = 'source';
|
|
5
|
+
export const holds = [
|
|
6
|
+
{
|
|
7
|
+
id: SOURCE_ROW,
|
|
8
|
+
section: 'the source',
|
|
9
|
+
is: 'en',
|
|
10
|
+
describes: 'Which language this app is written in. One name, and it has to be one of the languages declared below — everything else is a translation of it, and the wording commands ask for those and never for this one twice.',
|
|
11
|
+
version: 1,
|
|
12
|
+
},
|
|
13
|
+
];
|
|
14
|
+
export const declares = [
|
|
15
|
+
{
|
|
16
|
+
id: 'en',
|
|
17
|
+
at: fileFor('en'),
|
|
18
|
+
section: 'languages',
|
|
19
|
+
is: 'English',
|
|
20
|
+
sets: { flag: '🇬🇧' },
|
|
21
|
+
describes: 'English, and everything this app says in it. Named in its own language, because the list this feeds is read by somebody who cannot yet read the language the app is currently in.',
|
|
22
|
+
version: 1,
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
export const LOCALIZATIONS = {
|
|
26
|
+
id: 'localization',
|
|
27
|
+
at: 'thread/ui/localizations.ts',
|
|
28
|
+
files: fileFor('*'),
|
|
29
|
+
describes: 'Every language an app is in, and which one it is written in. A row is a language tag, the language’s name in itself and a flag to show beside it, so a settings screen offering a choice is built from declarations rather than from a list somebody keeps in a component. Adding a row is what brings a wording file for that language into existence, and every key the interface names has to be answered in every language declared here — an unanswered one is a build error rather than a word that silently comes out in the wrong language.',
|
|
30
|
+
version: 1,
|
|
31
|
+
cites: [
|
|
32
|
+
{
|
|
33
|
+
on: '2026-08-29',
|
|
34
|
+
said: 'i18n ships by default, nothing hardcoded in the UI at all. i18n is REQUIRED. We define the languages the app will have, this generates automatically the i18n files so that we can add the stuff there.',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
on: '2026-08-29',
|
|
38
|
+
said: 'This means that we need a new Localization.ts file under UI, where we declare the languages the app is in, must be threaded on attach. This might maybe include an emoji for the country flag? And name of the language so we can reuse this in settings later',
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
holds,
|
|
42
|
+
declares,
|
|
43
|
+
};
|
|
44
|
+
export function languagesIn(rows) {
|
|
45
|
+
return rows
|
|
46
|
+
.filter((row) => row.id !== SOURCE_ROW)
|
|
47
|
+
.map((row) => ({ id: row.id, name: row.is ?? row.id, flag: row.sets?.flag ?? '' }));
|
|
48
|
+
}
|
|
49
|
+
export function sourceIn(rows) {
|
|
50
|
+
return rows.find((row) => row.id === SOURCE_ROW)?.is;
|
|
51
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
import { argv, exit, stdout } from 'node:process';
|
|
12
|
+
import { pathToFileURL } from 'node:url';
|
|
13
|
+
import { ELSEWHERE, RECEIPT, answer, answering, asking, given, guidance, issue, marked, named, needed, only, prompted, refuse, spend, within, wordsIn, wrapped } from "@prestack/thread/core/asking";
|
|
14
|
+
import { named as packageOf } from "@prestack/thread/core/scope";
|
|
15
|
+
import { findTree, inTree } from "@prestack/thread/core/tree";
|
|
16
|
+
import { keyProps, keysIn, readWording, walk, wordingFile } from "../generators/i18n.js";
|
|
17
|
+
import { fileFor, languagesIn, sourceIn } from "../localizations.js";
|
|
18
|
+
const TREE = findTree();
|
|
19
|
+
const DOTTED = /^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$/;
|
|
20
|
+
const KEY = { at: 'key', guide: 'lowercase words joined by dots — `checkout.confirm`, `errors.db.not_found.title`' };
|
|
21
|
+
async function languages() {
|
|
22
|
+
const path = inTree(TREE, `localizations.${'ts'}`);
|
|
23
|
+
let sheet = {};
|
|
24
|
+
try {
|
|
25
|
+
sheet = (await import(__rewriteRelativeImportExtension(pathToFileURL(path).href)));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
sheet = {};
|
|
29
|
+
}
|
|
30
|
+
if (sheet.LOCALIZATION === undefined) {
|
|
31
|
+
refuse(`there is no ${within(TREE.at, path)} declaring a \`LOCALIZATION\` here, so this app is in no ` +
|
|
32
|
+
`language and a message has nowhere to go. Run \`npx thread attach ${packageOf('ui')}\`.`);
|
|
33
|
+
}
|
|
34
|
+
const rows = [...(sheet.LOCALIZATION.holds ?? []), ...(sheet.LOCALIZATION.declares ?? [])];
|
|
35
|
+
const held = languagesIn(rows);
|
|
36
|
+
const source = sourceIn(rows);
|
|
37
|
+
if (held.length === 0 || source === undefined) {
|
|
38
|
+
refuse('no language is declared, so there is nothing to write a message in. Add one with `npx thread create language`.');
|
|
39
|
+
}
|
|
40
|
+
return { held, source };
|
|
41
|
+
}
|
|
42
|
+
function usage(props) {
|
|
43
|
+
const found = new Map();
|
|
44
|
+
for (const file of walk(TREE.at)) {
|
|
45
|
+
const text = readFileSync(file, 'utf8');
|
|
46
|
+
for (const key of new Set(keysIn(text, props))) {
|
|
47
|
+
const held = found.get(key) ?? [];
|
|
48
|
+
held.push(within(TREE.at, file));
|
|
49
|
+
found.set(key, held);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return found;
|
|
53
|
+
}
|
|
54
|
+
const mark = (key, said) => marked([key, said]);
|
|
55
|
+
function write(at, language, held) {
|
|
56
|
+
writeFileSync(join(at, fileFor(language)), wordingFile(held), 'utf8');
|
|
57
|
+
}
|
|
58
|
+
async function run() {
|
|
59
|
+
const { held: spoken, source } = await languages();
|
|
60
|
+
const props = keyProps(TREE.at);
|
|
61
|
+
if (props.length === 0) {
|
|
62
|
+
refuse(`nothing in the installed \`${packageOf('ui')}\` declares a prop of type \`MessageKey\`, so no key could be ` +
|
|
63
|
+
'recognised anywhere. That is a broken install rather than an app with no wording.');
|
|
64
|
+
}
|
|
65
|
+
const LANGUAGES = spoken.map((one) => ({ at: one.id, guide: `what it says in ${one.name}` }));
|
|
66
|
+
const NEW = [KEY, ...LANGUAGES];
|
|
67
|
+
const wording = new Map();
|
|
68
|
+
for (const one of spoken)
|
|
69
|
+
wording.set(one.id, { ...readWording(TREE.at, one.id) });
|
|
70
|
+
const written = wording.get(source) ?? {};
|
|
71
|
+
const keys = Object.keys(written).sort();
|
|
72
|
+
const used = usage(props);
|
|
73
|
+
const blank = (key) => spoken.filter((one) => ((wording.get(one.id) ?? {})[key] ?? '') === '').map((one) => one.id);
|
|
74
|
+
const listing = [
|
|
75
|
+
`${String(keys.length)} message(s), in ${spoken.map((one) => one.id).join(', ')} — written in ${source}:`,
|
|
76
|
+
'',
|
|
77
|
+
...keys.map((key) => {
|
|
78
|
+
const missing = blank(key);
|
|
79
|
+
const said = (written[key] ?? '') || '(nothing yet)';
|
|
80
|
+
return (` [${mark(key, written[key] ?? '')}] ${key.padEnd(38)} ${said.length > 46 ? `${said.slice(0, 45)}…` : said}` +
|
|
81
|
+
`${missing.length === 0 ? '' : ` · still to write: ${missing.join(', ')}`}` +
|
|
82
|
+
`${(used.get(key) ?? []).length === 0 ? ' · named by nothing here' : ''}`);
|
|
83
|
+
}),
|
|
84
|
+
].join('\n');
|
|
85
|
+
const words = wordsIn(['new']);
|
|
86
|
+
const verb = words[0];
|
|
87
|
+
const flagged = argv.indexOf(RECEIPT);
|
|
88
|
+
if (flagged === -1) {
|
|
89
|
+
stdout.write(`${listing}\n`);
|
|
90
|
+
const nonce = issue(TREE.at, listing);
|
|
91
|
+
stdout.write([
|
|
92
|
+
'',
|
|
93
|
+
...answering('message'),
|
|
94
|
+
'',
|
|
95
|
+
...guidance(NEW),
|
|
96
|
+
'',
|
|
97
|
+
...wrapped('Every language is asked for and none may be left blank. A key that exists in one language and ' +
|
|
98
|
+
'not another is what makes a screen come out half translated, and it is refused here rather ' +
|
|
99
|
+
'than found by whoever is reading the app in the other one.', ' '),
|
|
100
|
+
'',
|
|
101
|
+
` npx thread create message new ${RECEIPT} ${nonce}`,
|
|
102
|
+
'',
|
|
103
|
+
...ELSEWHERE,
|
|
104
|
+
'',
|
|
105
|
+
...wrapped('A rename moves the wording in every language and rewrites every file in the interface that ' +
|
|
106
|
+
'names it, in one run.', ' '),
|
|
107
|
+
'',
|
|
108
|
+
].join('\n'));
|
|
109
|
+
stdout.write(`create: receipt ${nonce} — spent on use, and stale the moment the wording changes.\n`);
|
|
110
|
+
return 0;
|
|
111
|
+
}
|
|
112
|
+
spend(TREE.at, listing, argv[flagged + 1], `the wording`);
|
|
113
|
+
const all = given();
|
|
114
|
+
const { piped, ask, shut } = asking(all);
|
|
115
|
+
const ASKS = {
|
|
116
|
+
new: ['do', ...named(NEW)],
|
|
117
|
+
edit: ['do', 'mark', ...named(NEW)],
|
|
118
|
+
remove: ['do', 'mark'],
|
|
119
|
+
};
|
|
120
|
+
const doing = verb ?? (await ask('do', 'new, edit or remove: '));
|
|
121
|
+
const allowed = ASKS[doing];
|
|
122
|
+
if (allowed === undefined) {
|
|
123
|
+
shut();
|
|
124
|
+
refuse(`there is nothing called "${doing}" to do here — say new, edit, remove, or read, which needs no receipt`);
|
|
125
|
+
}
|
|
126
|
+
if (piped)
|
|
127
|
+
only(all, allowed, `\`${doing}\``);
|
|
128
|
+
if (doing === 'remove' || doing === 'edit') {
|
|
129
|
+
const which = words[1] ?? (piped ? needed(all, 'mark', `\`${doing}\``) : await ask('mark', 'mark: '));
|
|
130
|
+
const one = keys.find((key) => mark(key, written[key] ?? '') === which);
|
|
131
|
+
if (one === undefined) {
|
|
132
|
+
shut();
|
|
133
|
+
refuse(`\`${which}\` is not a mark this sheet issued — they are printed in brackets beside each message.`);
|
|
134
|
+
}
|
|
135
|
+
if (doing === 'remove') {
|
|
136
|
+
const where = used.get(one) ?? [];
|
|
137
|
+
if (where.length > 0) {
|
|
138
|
+
shut();
|
|
139
|
+
refuse(`\`${one}\` is named by ${where.slice(0, 6).join(', ')}` +
|
|
140
|
+
`${where.length > 6 ? ` and ${String(where.length - 6)} more` : ''}. ` +
|
|
141
|
+
'Removing it would leave those asking for wording that does not exist, which throws the moment ' +
|
|
142
|
+
'the screen renders. Take it out of the interface first.');
|
|
143
|
+
}
|
|
144
|
+
shut();
|
|
145
|
+
for (const language of spoken) {
|
|
146
|
+
const made = { ...(wording.get(language.id) ?? {}) };
|
|
147
|
+
delete made[one];
|
|
148
|
+
write(TREE.at, language.id, made);
|
|
149
|
+
}
|
|
150
|
+
stdout.write(`create: removed ${one} from ${String(spoken.length)} language file(s)\n`);
|
|
151
|
+
return 0;
|
|
152
|
+
}
|
|
153
|
+
const renamed = piped ? (answer(all, KEY.at) ?? '') : await ask(KEY.at, `key (${one}, blank to keep) `);
|
|
154
|
+
if (renamed !== '' && !DOTTED.test(renamed)) {
|
|
155
|
+
shut();
|
|
156
|
+
refuse(`\`${renamed}\` is not a key — lowercase words joined by dots.`);
|
|
157
|
+
}
|
|
158
|
+
if (renamed !== '' && written[renamed] !== undefined) {
|
|
159
|
+
shut();
|
|
160
|
+
refuse(`\`${renamed}\` is already a message. Two keys with one name is one key, and the other's wording is lost.`);
|
|
161
|
+
}
|
|
162
|
+
const said = new Map();
|
|
163
|
+
for (const language of spoken) {
|
|
164
|
+
const now = (wording.get(language.id) ?? {})[one] ?? '';
|
|
165
|
+
const next = piped
|
|
166
|
+
? (answer(all, language.id) ?? '')
|
|
167
|
+
: await ask(language.id, `${language.name} (${now || 'nothing yet'}) `);
|
|
168
|
+
said.set(language.id, next === '' ? now : next);
|
|
169
|
+
}
|
|
170
|
+
shut();
|
|
171
|
+
const name = renamed === '' ? one : renamed;
|
|
172
|
+
for (const language of spoken) {
|
|
173
|
+
const made = { ...(wording.get(language.id) ?? {}) };
|
|
174
|
+
delete made[one];
|
|
175
|
+
made[name] = said.get(language.id) ?? '';
|
|
176
|
+
write(TREE.at, language.id, made);
|
|
177
|
+
}
|
|
178
|
+
let moved = 0;
|
|
179
|
+
if (renamed !== '') {
|
|
180
|
+
for (const file of walk(TREE.at)) {
|
|
181
|
+
const text = readFileSync(file, 'utf8');
|
|
182
|
+
if (!keysIn(text, props).includes(one))
|
|
183
|
+
continue;
|
|
184
|
+
writeFileSync(file, text.replace(new RegExp(`(\\b(?:${props.join('|')})\\s*=\\s*")${one.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(")`, 'g'), `$1${name}$2`), 'utf8');
|
|
185
|
+
moved += 1;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
stdout.write(`create: ${one}${renamed === '' ? '' : ` is now ${name}`} — rewritten in ${String(spoken.length)} language file(s)` +
|
|
189
|
+
`${moved === 0 ? '' : ` and ${String(moved)} file(s) of the interface`}\n`);
|
|
190
|
+
const still = blankIn(said, spoken);
|
|
191
|
+
if (still.length > 0) {
|
|
192
|
+
stdout.write(`create: still nothing in ${still.join(', ')} — the gate refuses while that holds.\n`);
|
|
193
|
+
}
|
|
194
|
+
return 0;
|
|
195
|
+
}
|
|
196
|
+
const key = piped ? needed(all, KEY.at, '`new`') : await ask(KEY.at, prompted(KEY));
|
|
197
|
+
if (!DOTTED.test(key)) {
|
|
198
|
+
shut();
|
|
199
|
+
refuse(`\`${key}\` is not a key — lowercase words joined by dots, like \`checkout.confirm\`.`);
|
|
200
|
+
}
|
|
201
|
+
if (written[key] !== undefined) {
|
|
202
|
+
shut();
|
|
203
|
+
refuse(`\`${key}\` is already a message. Edit it by its mark, or choose another key.`);
|
|
204
|
+
}
|
|
205
|
+
const said = new Map();
|
|
206
|
+
for (const language of spoken) {
|
|
207
|
+
const next = piped
|
|
208
|
+
? (answer(all, language.id) ?? '')
|
|
209
|
+
: await ask(language.id, `what it says in ${language.name}: `);
|
|
210
|
+
if (next === '') {
|
|
211
|
+
shut();
|
|
212
|
+
refuse(`\`${key}\` has nothing to say in ${language.name}. Every language is answered at the moment a key ` +
|
|
213
|
+
'is made, because a key that exists in one language and not another is a screen that comes out ' +
|
|
214
|
+
'half translated. There is no way past this on purpose.');
|
|
215
|
+
}
|
|
216
|
+
said.set(language.id, next);
|
|
217
|
+
}
|
|
218
|
+
shut();
|
|
219
|
+
for (const language of spoken) {
|
|
220
|
+
write(TREE.at, language.id, { ...(wording.get(language.id) ?? {}), [key]: said.get(language.id) ?? '' });
|
|
221
|
+
}
|
|
222
|
+
stdout.write(`create: wrote ${key} in ${spoken.map((one) => one.id).join(', ')}\n`);
|
|
223
|
+
stdout.write(`create: name it in the interface with one of: ${props.join(', ')} — for example \`label="${key}"\`.\n`);
|
|
224
|
+
return 0;
|
|
225
|
+
}
|
|
226
|
+
function blankIn(said, spoken) {
|
|
227
|
+
return spoken.filter((one) => (said.get(one.id) ?? '') === '').map((one) => one.id);
|
|
228
|
+
}
|
|
229
|
+
if (argv[1] !== undefined)
|
|
230
|
+
exit(await run());
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { type Holds, type Token, type Wearing } from './token.ts';
|
|
2
|
+
export interface Setting {
|
|
3
|
+
readonly property: string;
|
|
4
|
+
readonly is?: string;
|
|
5
|
+
readonly token?: string;
|
|
6
|
+
readonly asks?: Readonly<Record<string, string | number>>;
|
|
7
|
+
}
|
|
8
|
+
export declare const BOUND: {
|
|
9
|
+
readonly background: readonly ["colour", "gradient", "texture", "noise", "img"];
|
|
10
|
+
readonly backgroundImage: readonly ["gradient", "texture", "noise", "img"];
|
|
11
|
+
readonly backdropFilter: readonly ["blur"];
|
|
12
|
+
readonly borderWidth: readonly ["edge"];
|
|
13
|
+
readonly borderStyle: readonly ["line"];
|
|
14
|
+
readonly borderColor: readonly ["colour"];
|
|
15
|
+
readonly boxShadow: readonly ["shadow"];
|
|
16
|
+
readonly color: readonly ["colour"];
|
|
17
|
+
readonly opacity: readonly ["opacity"];
|
|
18
|
+
};
|
|
19
|
+
type Property = keyof typeof BOUND;
|
|
20
|
+
type MaterialSettingFor<P extends Property> = {
|
|
21
|
+
readonly property: P;
|
|
22
|
+
readonly is?: string;
|
|
23
|
+
readonly token?: (typeof BOUND)[P][number];
|
|
24
|
+
readonly asks?: Readonly<Record<string, string | number>>;
|
|
25
|
+
};
|
|
26
|
+
type MaterialSetting = {
|
|
27
|
+
[P in Property]: MaterialSettingFor<P>;
|
|
28
|
+
}[Property];
|
|
29
|
+
export interface Material {
|
|
30
|
+
readonly id: string;
|
|
31
|
+
readonly sets: readonly MaterialSetting[];
|
|
32
|
+
readonly states?: readonly {
|
|
33
|
+
readonly when: readonly string[];
|
|
34
|
+
readonly sets: readonly MaterialSetting[];
|
|
35
|
+
}[];
|
|
36
|
+
readonly plays?: string;
|
|
37
|
+
readonly keyframes?: readonly {
|
|
38
|
+
readonly id: string;
|
|
39
|
+
readonly sets: Readonly<Record<string, readonly MaterialSetting[]>>;
|
|
40
|
+
}[];
|
|
41
|
+
}
|
|
42
|
+
export declare const FREE: readonly ["transition", "outline"];
|
|
43
|
+
export declare const material: <const T extends Material>(one: T & {
|
|
44
|
+
readonly sets: { readonly [I in keyof T["sets"]]: T["sets"][I] extends {
|
|
45
|
+
readonly is: infer Said;
|
|
46
|
+
} ? {
|
|
47
|
+
readonly is: Wearing<Said & string>;
|
|
48
|
+
} : unknown; };
|
|
49
|
+
} & (T extends {
|
|
50
|
+
readonly states: infer States;
|
|
51
|
+
} ? {
|
|
52
|
+
readonly states: { readonly [S in keyof States]: States[S] extends {
|
|
53
|
+
readonly sets: infer Sets;
|
|
54
|
+
} ? {
|
|
55
|
+
readonly sets: { readonly [I in keyof Sets]: Sets[I] extends {
|
|
56
|
+
readonly is: infer Said;
|
|
57
|
+
} ? {
|
|
58
|
+
readonly is: Wearing<Said & string>;
|
|
59
|
+
} : unknown; };
|
|
60
|
+
} : unknown; };
|
|
61
|
+
} : unknown) & (T extends {
|
|
62
|
+
readonly keyframes: infer Frames;
|
|
63
|
+
} ? {
|
|
64
|
+
readonly keyframes: { readonly [F in keyof Frames]: Frames[F] extends {
|
|
65
|
+
readonly sets: infer Stops;
|
|
66
|
+
} ? {
|
|
67
|
+
readonly sets: { readonly [Stop in keyof Stops]: { readonly [I in keyof Stops[Stop]]: Stops[Stop][I] extends {
|
|
68
|
+
readonly is: infer Said;
|
|
69
|
+
} ? {
|
|
70
|
+
readonly is: Wearing<Said & string>;
|
|
71
|
+
} : unknown; }; };
|
|
72
|
+
} : unknown; };
|
|
73
|
+
} : unknown)) => T;
|
|
74
|
+
export declare function composed(sets: readonly Setting[], named: ReadonlySet<string>, tokens: Readonly<Record<string, Token>>, by: string, kinds: Readonly<Record<string, string>>, bound: Readonly<Record<string, readonly string[]>>): Readonly<Record<string, Holds>>;
|
|
75
|
+
export declare function compose(material: Material, named: ReadonlySet<string>, tokens: Readonly<Record<string, Token>>, kinds: Readonly<Record<string, string>>): Readonly<Record<string, Holds>>;
|
|
76
|
+
export declare function keyframesOf(material: Material, named: ReadonlySet<string>, tokens: Readonly<Record<string, Token>>, kinds: Readonly<Record<string, string>>): readonly {
|
|
77
|
+
readonly id: string;
|
|
78
|
+
readonly stops: readonly {
|
|
79
|
+
readonly stop: string;
|
|
80
|
+
readonly made: Readonly<Record<string, Holds>>;
|
|
81
|
+
}[];
|
|
82
|
+
}[];
|
|
83
|
+
export {};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { held, naming, sheeted } from "./token.js";
|
|
2
|
+
export const BOUND = {
|
|
3
|
+
background: ['colour', 'gradient', 'texture', 'noise', 'img'],
|
|
4
|
+
backgroundImage: ['gradient', 'texture', 'noise', 'img'],
|
|
5
|
+
backdropFilter: ['blur'],
|
|
6
|
+
borderWidth: ['edge'],
|
|
7
|
+
borderStyle: ['line'],
|
|
8
|
+
borderColor: ['colour'],
|
|
9
|
+
boxShadow: ['shadow'],
|
|
10
|
+
color: ['colour'],
|
|
11
|
+
opacity: ['opacity'],
|
|
12
|
+
};
|
|
13
|
+
export const FREE = ['transition', 'outline'];
|
|
14
|
+
export const material = (one) => one;
|
|
15
|
+
function rowsIn(value) {
|
|
16
|
+
return value.split(/\s+/).filter((one) => one !== '');
|
|
17
|
+
}
|
|
18
|
+
function bounded(set, by, kinds, bound) {
|
|
19
|
+
const value = set.is ?? '';
|
|
20
|
+
const rows = rowsIn(value);
|
|
21
|
+
const allowed = bound[set.property];
|
|
22
|
+
if (allowed === undefined)
|
|
23
|
+
return;
|
|
24
|
+
for (const row of rows) {
|
|
25
|
+
const kind = kinds[row];
|
|
26
|
+
if (kind === undefined || allowed.includes(kind))
|
|
27
|
+
continue;
|
|
28
|
+
const list = allowed.map((one) => `\`${one}\``).join(' · ');
|
|
29
|
+
throw new Error(`\`${by}\` sets \`${set.property}\` to \`${row}\`, and \`${row}\` is a \`${kind}\` row. ` +
|
|
30
|
+
`\`${set.property}\` takes: ${list}.`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function valued(set, named, tokens, by, kinds, bound) {
|
|
34
|
+
if (set.is !== undefined && set.token !== undefined) {
|
|
35
|
+
throw new Error(`\`${by}\` states both a value and a token for \`${set.property}\`. A property is either a ` +
|
|
36
|
+
'value the style guide holds or a token asked for one, never both.');
|
|
37
|
+
}
|
|
38
|
+
if (set.is !== undefined) {
|
|
39
|
+
if (kinds !== undefined)
|
|
40
|
+
bounded(set, by, kinds, bound);
|
|
41
|
+
return naming(named, set.is, by, set.property);
|
|
42
|
+
}
|
|
43
|
+
if (set.token === undefined) {
|
|
44
|
+
throw new Error(`\`${by}\` sets \`${set.property}\` to nothing. State a value with \`is\`, or name a token ` +
|
|
45
|
+
'and what to ask it for.');
|
|
46
|
+
}
|
|
47
|
+
const token = tokens[set.token];
|
|
48
|
+
if (token === undefined) {
|
|
49
|
+
throw new Error(`\`${by}\` asks \`${set.token}\` for \`${set.property}\`, and no token by that name is ` +
|
|
50
|
+
'declared. A token has to exist before anything can ask it for a value.');
|
|
51
|
+
}
|
|
52
|
+
if (token.makes === undefined) {
|
|
53
|
+
throw new Error(`\`${by}\` asks \`${set.token}\` for \`${set.property}\`, and \`${set.token}\` carries no ` +
|
|
54
|
+
'rule, so there is nothing to ask. Name a style guide value instead.');
|
|
55
|
+
}
|
|
56
|
+
return held(named, token.makes(set.asks ?? {}), by);
|
|
57
|
+
}
|
|
58
|
+
export function composed(sets, named, tokens, by, kinds, bound) {
|
|
59
|
+
const made = {};
|
|
60
|
+
for (const set of sets) {
|
|
61
|
+
if (bound[set.property] === undefined && (set.property === 'animation' || set.property === 'animationName')) {
|
|
62
|
+
throw new Error(`\`${by}\` sets \`${set.property}\` itself, which buries the keyframes name inside a ` +
|
|
63
|
+
'string where nothing can check it. Name a style guide row of the `animation` kind, or ' +
|
|
64
|
+
'declare keyframes and name them with `plays`.');
|
|
65
|
+
}
|
|
66
|
+
made[set.property] = valued(set, named, tokens, by, kinds, bound);
|
|
67
|
+
}
|
|
68
|
+
return made;
|
|
69
|
+
}
|
|
70
|
+
function playing(material, plays) {
|
|
71
|
+
if (plays === undefined)
|
|
72
|
+
return {};
|
|
73
|
+
if ((material.keyframes ?? []).some((one) => one.id === plays))
|
|
74
|
+
return { animationName: sheeted(material.id, plays) };
|
|
75
|
+
const declared = (material.keyframes ?? []).map((one) => one.id);
|
|
76
|
+
throw new Error(`\`${material.id}\` plays \`${plays}\`, and declares no keyframes by that name. ` +
|
|
77
|
+
(declared.length === 0
|
|
78
|
+
? 'It declares none at all, so there is nothing for it to play.'
|
|
79
|
+
: `It declares: ${declared.join(' · ')}.`));
|
|
80
|
+
}
|
|
81
|
+
export function compose(material, named, tokens, kinds) {
|
|
82
|
+
return {
|
|
83
|
+
...composed(material.sets, named, tokens, material.id, kinds, BOUND),
|
|
84
|
+
...playing(material, material.plays),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export function keyframesOf(material, named, tokens, kinds) {
|
|
88
|
+
return (material.keyframes ?? []).map((one) => ({
|
|
89
|
+
id: one.id,
|
|
90
|
+
stops: Object.keys(one.sets).map((stop) => ({
|
|
91
|
+
stop,
|
|
92
|
+
made: composed(one.sets[stop] ?? [], named, tokens, material.id, kinds, BOUND),
|
|
93
|
+
})),
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const BORDERED: {
|
|
2
|
+
readonly id: "bordered";
|
|
3
|
+
readonly sets: readonly [{
|
|
4
|
+
readonly property: "background";
|
|
5
|
+
readonly is: "colour-surface";
|
|
6
|
+
}, {
|
|
7
|
+
readonly property: "borderWidth";
|
|
8
|
+
readonly is: "edge-thick";
|
|
9
|
+
}, {
|
|
10
|
+
readonly property: "borderStyle";
|
|
11
|
+
readonly is: "line-solid";
|
|
12
|
+
}, {
|
|
13
|
+
readonly property: "borderColor";
|
|
14
|
+
readonly is: "colour-ink";
|
|
15
|
+
}, {
|
|
16
|
+
readonly property: "boxShadow";
|
|
17
|
+
readonly is: "shadow-hard";
|
|
18
|
+
}, {
|
|
19
|
+
readonly property: "color";
|
|
20
|
+
readonly is: "colour-ink";
|
|
21
|
+
}];
|
|
22
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { material } from "../material.js";
|
|
2
|
+
export const BORDERED = material({
|
|
3
|
+
id: 'bordered',
|
|
4
|
+
sets: [
|
|
5
|
+
{ property: 'background', is: 'colour-surface' },
|
|
6
|
+
{ property: 'borderWidth', is: 'edge-thick' },
|
|
7
|
+
{ property: 'borderStyle', is: 'line-solid' },
|
|
8
|
+
{ property: 'borderColor', is: 'colour-ink' },
|
|
9
|
+
{ property: 'boxShadow', is: 'shadow-hard' },
|
|
10
|
+
{ property: 'color', is: 'colour-ink' },
|
|
11
|
+
],
|
|
12
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const CERAMIC: {
|
|
2
|
+
readonly id: "ceramic";
|
|
3
|
+
readonly sets: readonly [{
|
|
4
|
+
readonly property: "backgroundImage";
|
|
5
|
+
readonly is: "gradient-sheen";
|
|
6
|
+
}, {
|
|
7
|
+
readonly property: "borderWidth";
|
|
8
|
+
readonly is: "edge-hair";
|
|
9
|
+
}, {
|
|
10
|
+
readonly property: "borderStyle";
|
|
11
|
+
readonly is: "line-solid";
|
|
12
|
+
}, {
|
|
13
|
+
readonly property: "borderColor";
|
|
14
|
+
readonly is: "colour-edge-ceramic";
|
|
15
|
+
}, {
|
|
16
|
+
readonly property: "boxShadow";
|
|
17
|
+
readonly is: "shadow-2";
|
|
18
|
+
}, {
|
|
19
|
+
readonly property: "color";
|
|
20
|
+
readonly is: "colour-ink";
|
|
21
|
+
}];
|
|
22
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { material } from "../material.js";
|
|
2
|
+
export const CERAMIC = material({
|
|
3
|
+
id: 'ceramic',
|
|
4
|
+
sets: [
|
|
5
|
+
{ property: 'backgroundImage', is: 'gradient-sheen' },
|
|
6
|
+
{ property: 'borderWidth', is: 'edge-hair' },
|
|
7
|
+
{ property: 'borderStyle', is: 'line-solid' },
|
|
8
|
+
{ property: 'borderColor', is: 'colour-edge-ceramic' },
|
|
9
|
+
{ property: 'boxShadow', is: 'shadow-2' },
|
|
10
|
+
{ property: 'color', is: 'colour-ink' },
|
|
11
|
+
],
|
|
12
|
+
});
|