@flickfyi/flkr 0.0.182 → 0.0.185
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/{api-client-CAg1b8Bh.js → api-client-nn4U_Vfn.js} +1 -1
- package/dist/{app-DpM5nhb9.js → app-COXGJhrt.js} +3 -3
- package/dist/{bundler-DNrDcqyk.js → bundler-CW4YC73e.js} +4 -2
- package/dist/cli.js +11 -11
- package/dist/{delegate-DcVye0KE.js → delegate-aUVluBjB.js} +2 -2
- package/dist/{generate-B1l1z_FZ.js → generate-BeL1QPDi.js} +1 -1
- package/dist/{preview-Dqn_Tq6K.js → preview-DTVM8Csb.js} +2 -2
- package/dist/{publish-BmDqO1xU.js → publish-BJG-s-w5.js} +4 -4
- package/dist/{pull-CO80DMn8.js → pull-B_Yfjpi2.js} +1 -1
- package/dist/{save-8crfOeo1.js → save-UrfgmK2-.js} +2 -2
- package/dist/{sdk-app-BXWrf_pf.js → sdk-app-BAxznAf9.js} +3 -3
- package/dist/{sdk-deploy-CaEonlvx.js → sdk-deploy-D1wgQxse.js} +3 -3
- package/dist/{sdk-generation-CF8ATbrL.js → sdk-generation-CLQ-QrVM.js} +1 -1
- package/dist/{sdk-project-CKV3U3u9.js → sdk-project-BaO0fqhW.js} +1 -1
- package/dist/{use-auth-B6nwU2rp.js → use-auth-CtM4_BAY.js} +1 -1
- package/node_modules/@flickfyi/biscuit/.turbo/turbo-build.log +4 -4
- package/node_modules/@flickfyi/core/README.md +19 -9
- package/node_modules/@flickfyi/core/dist/chunks/{default-CuxDsQoM.js → default-BTmKidHV.js} +1 -1
- package/node_modules/@flickfyi/core/dist/chunks/{default-BB6YexEH.cjs → default-JhTq5I_y.cjs} +1 -1
- package/node_modules/@flickfyi/core/dist/chunks/{define-CUJRqVKY.cjs → define-BKCRhpuY.cjs} +1 -1
- package/node_modules/@flickfyi/core/dist/chunks/{define-e_VqSs4M.js → define-DZXgUsy7.js} +5 -5
- package/node_modules/@flickfyi/core/dist/kowalski/catalog.cjs +1 -1
- package/node_modules/@flickfyi/core/dist/kowalski/catalog.js +728 -549
- package/node_modules/@flickfyi/core/dist/kowalski/index.cjs +5 -5
- package/node_modules/@flickfyi/core/dist/kowalski/index.js +4297 -3700
- package/node_modules/@flickfyi/core/dist/kowalski/schemas.cjs +1 -0
- package/node_modules/@flickfyi/core/dist/kowalski/schemas.js +637 -0
- package/node_modules/@flickfyi/core/dist/kowalski-catalog.css +516 -0
- package/node_modules/@flickfyi/core/dist/kowalski.css +10 -0
- package/node_modules/@flickfyi/core/dist/themes/athletic/athletic.cjs +1 -1
- package/node_modules/@flickfyi/core/dist/themes/athletic/athletic.js +1 -1
- package/node_modules/@flickfyi/core/dist/themes/compact/compact.cjs +1 -1
- package/node_modules/@flickfyi/core/dist/themes/compact/compact.js +1 -1
- package/node_modules/@flickfyi/core/dist/themes/default/default.cjs +1 -1
- package/node_modules/@flickfyi/core/dist/themes/default/default.js +1 -1
- package/node_modules/@flickfyi/core/dist/themes/editorial/editorial.cjs +1 -1
- package/node_modules/@flickfyi/core/dist/themes/editorial/editorial.js +1 -1
- package/node_modules/@flickfyi/core/dist/themes/handwritten/handwritten.cjs +1 -1
- package/node_modules/@flickfyi/core/dist/themes/handwritten/handwritten.js +1 -1
- package/node_modules/@flickfyi/core/dist/themes/index.cjs +1 -1
- package/node_modules/@flickfyi/core/dist/themes/index.js +1 -1
- package/node_modules/@flickfyi/core/dist/themes/kids/kids.cjs +1 -1
- package/node_modules/@flickfyi/core/dist/themes/kids/kids.js +1 -1
- package/node_modules/@flickfyi/core/dist/themes/rounded/rounded.cjs +1 -1
- package/node_modules/@flickfyi/core/dist/themes/rounded/rounded.js +1 -1
- package/node_modules/@flickfyi/core/dist/themes/technical/technical.cjs +1 -1
- package/node_modules/@flickfyi/core/dist/themes/technical/technical.js +1 -1
- package/node_modules/@flickfyi/core/dist-types/hooks/use-feature-store/index.d.ts +43 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/calculations.d.ts +57 -3
- package/node_modules/@flickfyi/core/dist-types/kowalski/calculator.d.ts +7 -6
- package/node_modules/@flickfyi/core/dist-types/kowalski/catalog.d.cts +524 -809
- package/node_modules/@flickfyi/core/dist-types/kowalski/catalog.d.ts +524 -809
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/bill-split.d.ts +38 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/bookmark.d.ts +48 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/budget.d.ts +39 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/calculator.d.ts +62 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/checklist.d.ts +35 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/color-palette.d.ts +32 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/contact.d.ts +41 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/countdown.d.ts +34 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/event.d.ts +43 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/expense.d.ts +40 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/goal.d.ts +36 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/habit.d.ts +57 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/ledger.d.ts +43 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/note.d.ts +35 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/poll.d.ts +41 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/random-picker.d.ts +69 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/rating.d.ts +33 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/reminder.d.ts +48 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/rotation.d.ts +39 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/scoreboard.d.ts +37 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/shopping-list.d.ts +41 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/task-board.d.ts +39 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/time-zone.d.ts +34 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/timer.d.ts +43 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/trip.d.ts +61 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/components/unit-converter.d.ts +106 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/create-schemas.d.ts +6 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/date-time.d.ts +1 -1
- package/node_modules/@flickfyi/core/dist-types/kowalski/everyday.d.ts +28 -8
- package/node_modules/@flickfyi/core/dist-types/kowalski/feature-schema.d.ts +65 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/format.d.ts +4 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/fortune.d.ts +21 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/frame.d.ts +4 -4
- package/node_modules/@flickfyi/core/dist-types/kowalski/index.d.cts +31 -7
- package/node_modules/@flickfyi/core/dist-types/kowalski/index.d.ts +31 -7
- package/node_modules/@flickfyi/core/dist-types/kowalski/lesson.d.ts +89 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/recipe.d.ts +129 -8
- package/node_modules/@flickfyi/core/dist-types/kowalski/schemas.d.cts +4 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/schemas.d.ts +4 -0
- package/node_modules/@flickfyi/core/dist-types/kowalski/time-since.d.ts +34 -0
- package/node_modules/@flickfyi/core/examples/example-metadata.ts +19 -2
- package/node_modules/@flickfyi/core/examples/kowalski/bill-split/bill-split.stories.tsx +25 -6
- package/node_modules/@flickfyi/core/examples/kowalski/bill-split/bill-split.tsx +6 -12
- package/node_modules/@flickfyi/core/examples/kowalski/bookmark/bookmark.stories.tsx +22 -5
- package/node_modules/@flickfyi/core/examples/kowalski/bookmark/bookmark.tsx +6 -18
- package/node_modules/@flickfyi/core/examples/kowalski/budget/budget.stories.tsx +26 -5
- package/node_modules/@flickfyi/core/examples/kowalski/budget/budget.tsx +6 -21
- package/node_modules/@flickfyi/core/examples/kowalski/calculator/calculator.stories.tsx +18 -5
- package/node_modules/@flickfyi/core/examples/kowalski/calculator/calculator.tsx +6 -19
- package/node_modules/@flickfyi/core/examples/kowalski/checklist/checklist.stories.tsx +25 -5
- package/node_modules/@flickfyi/core/examples/kowalski/checklist/checklist.tsx +6 -21
- package/node_modules/@flickfyi/core/examples/kowalski/color-palette/color-palette.stories.tsx +19 -6
- package/node_modules/@flickfyi/core/examples/kowalski/color-palette/color-palette.tsx +6 -17
- package/node_modules/@flickfyi/core/examples/kowalski/contact/contact.stories.tsx +30 -5
- package/node_modules/@flickfyi/core/examples/kowalski/contact/contact.tsx +6 -18
- package/node_modules/@flickfyi/core/examples/kowalski/countdown/countdown.stories.tsx +22 -5
- package/node_modules/@flickfyi/core/examples/kowalski/countdown/countdown.tsx +6 -18
- package/node_modules/@flickfyi/core/examples/kowalski/event/event.stories.tsx +23 -5
- package/node_modules/@flickfyi/core/examples/kowalski/event/event.tsx +6 -19
- package/node_modules/@flickfyi/core/examples/kowalski/expense/expense.stories.tsx +23 -5
- package/node_modules/@flickfyi/core/examples/kowalski/expense/expense.tsx +6 -18
- package/node_modules/@flickfyi/core/examples/kowalski/fortune/fortune.stories.tsx +61 -0
- package/node_modules/@flickfyi/core/examples/kowalski/fortune/fortune.tsx +11 -0
- package/node_modules/@flickfyi/core/examples/kowalski/goal/goal.stories.tsx +18 -5
- package/node_modules/@flickfyi/core/examples/kowalski/goal/goal.tsx +3 -19
- package/node_modules/@flickfyi/core/examples/kowalski/habit/habit.stories.tsx +22 -5
- package/node_modules/@flickfyi/core/examples/kowalski/habit/habit.tsx +6 -18
- package/node_modules/@flickfyi/core/examples/kowalski/ledger/ledger.stories.tsx +25 -5
- package/node_modules/@flickfyi/core/examples/kowalski/ledger/ledger.tsx +6 -20
- package/node_modules/@flickfyi/core/examples/kowalski/lesson/lesson.stories.tsx +99 -0
- package/node_modules/@flickfyi/core/examples/kowalski/lesson/lesson.tsx +11 -0
- package/node_modules/@flickfyi/core/examples/kowalski/note/note.stories.tsx +21 -5
- package/node_modules/@flickfyi/core/examples/kowalski/note/note.tsx +3 -17
- package/node_modules/@flickfyi/core/examples/kowalski/poll/poll.stories.tsx +26 -5
- package/node_modules/@flickfyi/core/examples/kowalski/poll/poll.tsx +3 -21
- package/node_modules/@flickfyi/core/examples/kowalski/random-picker/random-picker.stories.tsx +37 -6
- package/node_modules/@flickfyi/core/examples/kowalski/random-picker/random-picker.tsx +6 -18
- package/node_modules/@flickfyi/core/examples/kowalski/rating/rating.stories.tsx +18 -5
- package/node_modules/@flickfyi/core/examples/kowalski/rating/rating.tsx +6 -14
- package/node_modules/@flickfyi/core/examples/kowalski/recipe/recipe.stories.tsx +117 -5
- package/node_modules/@flickfyi/core/examples/kowalski/recipe/recipe.tsx +6 -115
- package/node_modules/@flickfyi/core/examples/kowalski/reminder/reminder.stories.tsx +22 -5
- package/node_modules/@flickfyi/core/examples/kowalski/reminder/reminder.tsx +6 -18
- package/node_modules/@flickfyi/core/examples/kowalski/rotation/rotation.stories.tsx +26 -5
- package/node_modules/@flickfyi/core/examples/kowalski/rotation/rotation.tsx +6 -22
- package/node_modules/@flickfyi/core/examples/kowalski/scoreboard/scoreboard.stories.tsx +26 -5
- package/node_modules/@flickfyi/core/examples/kowalski/scoreboard/scoreboard.tsx +6 -21
- package/node_modules/@flickfyi/core/examples/kowalski/shopping-list/shopping-list.stories.tsx +28 -6
- package/node_modules/@flickfyi/core/examples/kowalski/shopping-list/shopping-list.tsx +6 -22
- package/node_modules/@flickfyi/core/examples/kowalski/task-board/task-board.stories.tsx +27 -6
- package/node_modules/@flickfyi/core/examples/kowalski/task-board/task-board.tsx +6 -22
- package/node_modules/@flickfyi/core/examples/kowalski/time-since/time-since.stories.tsx +33 -0
- package/node_modules/@flickfyi/core/examples/kowalski/time-since/time-since.tsx +12 -0
- package/node_modules/@flickfyi/core/examples/kowalski/time-zone/time-zone.stories.tsx +22 -6
- package/node_modules/@flickfyi/core/examples/kowalski/time-zone/time-zone.tsx +6 -17
- package/node_modules/@flickfyi/core/examples/kowalski/timer/timer.stories.tsx +18 -5
- package/node_modules/@flickfyi/core/examples/kowalski/timer/timer.tsx +6 -18
- package/node_modules/@flickfyi/core/examples/kowalski/trip/trip.stories.tsx +25 -5
- package/node_modules/@flickfyi/core/examples/kowalski/trip/trip.tsx +3 -21
- package/node_modules/@flickfyi/core/examples/kowalski/unit-converter/unit-converter.stories.tsx +19 -6
- package/node_modules/@flickfyi/core/examples/kowalski/unit-converter/unit-converter.tsx +6 -19
- package/node_modules/@flickfyi/core/examples/parrott/calculator/calculator.stories.tsx +10 -3
- package/node_modules/@flickfyi/core/examples/parrott/calculator/calculator.tsx +2 -13
- package/node_modules/@flickfyi/core/examples/parrott/checklist/checklist.stories.tsx +10 -3
- package/node_modules/@flickfyi/core/examples/parrott/checklist/checklist.tsx +0 -8
- package/node_modules/@flickfyi/core/examples/parrott/countdown/countdown.stories.tsx +10 -3
- package/node_modules/@flickfyi/core/examples/parrott/countdown/countdown.tsx +0 -8
- package/node_modules/@flickfyi/core/examples/parrott/counter/counter.stories.tsx +10 -3
- package/node_modules/@flickfyi/core/examples/parrott/counter/counter.tsx +0 -8
- package/node_modules/@flickfyi/core/examples/parrott/fortune/fortune.stories.tsx +10 -3
- package/node_modules/@flickfyi/core/examples/parrott/fortune/fortune.tsx +0 -8
- package/node_modules/@flickfyi/core/examples/parrott/grid/grid.stories.tsx +10 -3
- package/node_modules/@flickfyi/core/examples/parrott/grid/grid.tsx +4 -9
- package/node_modules/@flickfyi/core/examples/parrott/kale-smoothie/kale-smoothie.stories.tsx +10 -3
- package/node_modules/@flickfyi/core/examples/parrott/kale-smoothie/kale-smoothie.tsx +0 -8
- package/node_modules/@flickfyi/core/examples/parrott/list/list.stories.tsx +10 -3
- package/node_modules/@flickfyi/core/examples/parrott/list/list.tsx +0 -8
- package/node_modules/@flickfyi/core/examples/parrott/log/log.stories.tsx +10 -3
- package/node_modules/@flickfyi/core/examples/parrott/log/log.tsx +0 -8
- package/node_modules/@flickfyi/core/examples/parrott/timed-task/timed-task.stories.tsx +10 -3
- package/node_modules/@flickfyi/core/examples/parrott/timed-task/timed-task.tsx +0 -8
- package/node_modules/@flickfyi/core/examples/parrott/timer/timer.stories.tsx +10 -3
- package/node_modules/@flickfyi/core/examples/parrott/timer/timer.tsx +0 -8
- package/node_modules/@flickfyi/core/package.json +16 -3
- package/node_modules/@flickfyi/core/src/{kowalski/use-configured-feature.ts → hooks/use-configured-feature/index.ts} +1 -1
- package/node_modules/@flickfyi/core/src/{kowalski/use-feature-store.ts → hooks/use-feature-store/index.ts} +37 -12
- package/node_modules/@flickfyi/core/src/kowalski/README.md +13 -0
- package/node_modules/@flickfyi/core/src/kowalski/calculations.ts +36 -8
- package/node_modules/@flickfyi/core/src/kowalski/calculator.ts +15 -7
- package/node_modules/@flickfyi/core/src/kowalski/catalog.ts +110 -704
- package/node_modules/@flickfyi/core/src/kowalski/components/bill-split.tsx +284 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/bookmark.tsx +347 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/budget.tsx +169 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/calculator.tsx +202 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/checklist.tsx +119 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/color-palette.tsx +302 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/contact.tsx +247 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/countdown.tsx +173 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/event.tsx +260 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/expense.tsx +257 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/goal.tsx +182 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/habit.tsx +272 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/ledger.tsx +211 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/note.tsx +188 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/poll.tsx +242 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/random-picker.tsx +308 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/rating.tsx +112 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/reminder.tsx +298 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/rotation.tsx +146 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/scoreboard.tsx +139 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/shopping-list.tsx +144 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/task-board.tsx +146 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/time-zone.tsx +240 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/timer.tsx +225 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/trip.tsx +338 -0
- package/node_modules/@flickfyi/core/src/kowalski/components/unit-converter.tsx +285 -0
- package/node_modules/@flickfyi/core/src/kowalski/create-schemas.ts +8 -0
- package/node_modules/@flickfyi/core/src/kowalski/date-time.tsx +1 -1
- package/node_modules/@flickfyi/core/src/kowalski/everyday.tsx +1 -640
- package/node_modules/@flickfyi/core/src/kowalski/feature-schema.ts +84 -0
- package/node_modules/@flickfyi/core/src/kowalski/format.ts +29 -3
- package/node_modules/@flickfyi/core/src/kowalski/fortune.tsx +67 -0
- package/node_modules/@flickfyi/core/src/kowalski/frame.tsx +5 -6
- package/node_modules/@flickfyi/core/src/kowalski/index.ts +31 -22
- package/node_modules/@flickfyi/core/src/kowalski/lesson.tsx +564 -0
- package/node_modules/@flickfyi/core/src/kowalski/recipe.tsx +78 -37
- package/node_modules/@flickfyi/core/src/kowalski/schemas.ts +67 -0
- package/node_modules/@flickfyi/core/src/kowalski/stories/composition.tsx +22 -20
- package/node_modules/@flickfyi/core/src/kowalski/time-since.tsx +145 -0
- package/node_modules/@flickfyi/core/src/molecules/progress/progress.tsx +4 -1
- package/node_modules/@flickfyi/core/src/oklch.ts +1 -6
- package/node_modules/@flickfyi/core/src/parrott/theme.ts +3 -1
- package/node_modules/@flickfyi/core/src/themes/editorial/editorial.ts +6 -1
- package/node_modules/@flickfyi/core/src/themes/palette.ts +5 -5
- package/node_modules/@flickfyi/core/src/themes/stories/composition.tsx +11 -9
- package/node_modules/@flickfyi/core/src/themes/stories/gallery.tsx +7 -11
- package/node_modules/@flickfyi/core/tsgo.bun.lock +7 -7
- package/node_modules/@flickfyi/core/tsgo.package.json +1 -1
- package/package.json +2 -2
- package/node_modules/@flickfyi/core/dist-types/kowalski/clocks.d.ts +0 -4
- package/node_modules/@flickfyi/core/dist-types/kowalski/details.d.ts +0 -7
- package/node_modules/@flickfyi/core/dist-types/kowalski/productivity.d.ts +0 -5
- package/node_modules/@flickfyi/core/dist-types/kowalski/tools.d.ts +0 -7
- package/node_modules/@flickfyi/core/dist-types/kowalski/use-feature-store.d.ts +0 -15
- package/node_modules/@flickfyi/core/src/kowalski/clocks.tsx +0 -464
- package/node_modules/@flickfyi/core/src/kowalski/details.tsx +0 -1387
- package/node_modules/@flickfyi/core/src/kowalski/productivity.tsx +0 -575
- package/node_modules/@flickfyi/core/src/kowalski/tools.tsx +0 -1213
- /package/node_modules/@flickfyi/core/dist-types/{kowalski/use-clock.d.ts → hooks/use-clock/index.d.ts} +0 -0
- /package/node_modules/@flickfyi/core/dist-types/{kowalski/use-configured-feature.d.ts → hooks/use-configured-feature/index.d.ts} +0 -0
- /package/node_modules/@flickfyi/core/src/{kowalski/use-clock.ts → hooks/use-clock/index.ts} +0 -0
|
@@ -1,787 +1,193 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
1
|
+
import { BillSplitProps } from '~/kowalski/components/bill-split'
|
|
2
|
+
import { BookmarkProps } from '~/kowalski/components/bookmark'
|
|
3
|
+
import { BudgetProps } from '~/kowalski/components/budget'
|
|
4
|
+
import { CalculatorProps } from '~/kowalski/components/calculator'
|
|
5
|
+
import { ChecklistProps } from '~/kowalski/components/checklist'
|
|
6
|
+
import { ColorPaletteProps } from '~/kowalski/components/color-palette'
|
|
7
|
+
import { ContactProps } from '~/kowalski/components/contact'
|
|
8
|
+
import { CountdownProps } from '~/kowalski/components/countdown'
|
|
9
|
+
import { EventProps } from '~/kowalski/components/event'
|
|
10
|
+
import { ExpenseProps } from '~/kowalski/components/expense'
|
|
11
|
+
import { GoalProps } from '~/kowalski/components/goal'
|
|
12
|
+
import { HabitProps } from '~/kowalski/components/habit'
|
|
13
|
+
import { LedgerProps } from '~/kowalski/components/ledger'
|
|
14
|
+
import { NoteProps } from '~/kowalski/components/note'
|
|
15
|
+
import { PollProps } from '~/kowalski/components/poll'
|
|
16
|
+
import { RandomPickerProps } from '~/kowalski/components/random-picker'
|
|
17
|
+
import { RatingProps } from '~/kowalski/components/rating'
|
|
18
|
+
import { ReminderProps } from '~/kowalski/components/reminder'
|
|
19
|
+
import { RotationProps } from '~/kowalski/components/rotation'
|
|
20
|
+
import { ScoreboardProps } from '~/kowalski/components/scoreboard'
|
|
21
|
+
import { ShoppingListProps } from '~/kowalski/components/shopping-list'
|
|
22
|
+
import { TaskBoardProps } from '~/kowalski/components/task-board'
|
|
23
|
+
import { TimeZoneProps } from '~/kowalski/components/time-zone'
|
|
24
|
+
import { TimerProps } from '~/kowalski/components/timer'
|
|
25
|
+
import { TripProps } from '~/kowalski/components/trip'
|
|
26
|
+
import { UnitConverterProps } from '~/kowalski/components/unit-converter'
|
|
27
|
+
|
|
28
|
+
import { FortuneProps } from './fortune'
|
|
29
|
+
import { LessonProps } from './lesson'
|
|
30
|
+
import { RecipeProps } from './recipe'
|
|
31
|
+
import { TimeSinceProps } from './time-since'
|
|
32
|
+
|
|
33
|
+
export { unitDefinitions } from './calculations'
|
|
34
|
+
export {
|
|
35
|
+
type KowalskiComponent,
|
|
36
|
+
kowalskiComponentSchema,
|
|
37
|
+
kowalskiFeatureId,
|
|
38
|
+
kowalskiScope,
|
|
39
|
+
} from './feature-schema'
|
|
40
|
+
export { FortuneData } from './fortune'
|
|
41
|
+
export { LessonData } from './lesson'
|
|
42
|
+
export { RecipeData } from './recipe'
|
|
43
|
+
export { TimeSinceData } from './time-since'
|
|
44
|
+
export { BillSplitData } from '~/kowalski/components/bill-split'
|
|
45
|
+
export { BookmarkData, webAddressOptions } from '~/kowalski/components/bookmark'
|
|
46
|
+
export { BudgetData } from '~/kowalski/components/budget'
|
|
47
|
+
export { CalculatorData } from '~/kowalski/components/calculator'
|
|
48
|
+
export { ChecklistData } from '~/kowalski/components/checklist'
|
|
49
|
+
export { ColorPaletteData } from '~/kowalski/components/color-palette'
|
|
50
|
+
export { ContactData } from '~/kowalski/components/contact'
|
|
51
|
+
export { CountdownData } from '~/kowalski/components/countdown'
|
|
52
|
+
export { EventData } from '~/kowalski/components/event'
|
|
53
|
+
export { ExpenseData } from '~/kowalski/components/expense'
|
|
54
|
+
export { GoalData } from '~/kowalski/components/goal'
|
|
55
|
+
export { HabitData } from '~/kowalski/components/habit'
|
|
56
|
+
export { LedgerData } from '~/kowalski/components/ledger'
|
|
57
|
+
export { NoteData } from '~/kowalski/components/note'
|
|
58
|
+
export { PollData, pollVoterSchema } from '~/kowalski/components/poll'
|
|
59
|
+
export { RandomPickerData } from '~/kowalski/components/random-picker'
|
|
60
|
+
export { RatingData } from '~/kowalski/components/rating'
|
|
61
|
+
export { ReminderData } from '~/kowalski/components/reminder'
|
|
62
|
+
export { RotationData } from '~/kowalski/components/rotation'
|
|
63
|
+
export { ScoreboardData } from '~/kowalski/components/scoreboard'
|
|
64
|
+
export { ShoppingListData } from '~/kowalski/components/shopping-list'
|
|
65
|
+
export { TaskBoardData } from '~/kowalski/components/task-board'
|
|
66
|
+
export { TimeZoneData } from '~/kowalski/components/time-zone'
|
|
67
|
+
export { TimerData } from '~/kowalski/components/timer'
|
|
68
|
+
export { TripData } from '~/kowalski/components/trip'
|
|
69
|
+
export { UnitConverterData } from '~/kowalski/components/unit-converter'
|
|
70
|
+
|
|
71
|
+
/** Contracts shared by Core, Florge, and the catalog. */
|
|
35
72
|
export const kowalskiCatalog = {
|
|
36
73
|
billSplit: {
|
|
37
|
-
description:
|
|
38
|
-
'Split a bill equally with an optional tip, rounding in the selected currency.',
|
|
39
74
|
exportName: 'BillSplit',
|
|
40
|
-
props:
|
|
41
|
-
currency: currency(),
|
|
42
|
-
people: z.number().int().min(1).max(1000),
|
|
43
|
-
tipPercent: z.number().min(0).max(100).default(0),
|
|
44
|
-
title: title('Split the bill'),
|
|
45
|
-
total: z.number().min(0).max(1e12),
|
|
46
|
-
}),
|
|
47
|
-
storeSchema: store({
|
|
48
|
-
people: z.number().int().min(1).max(1000).default(1),
|
|
49
|
-
tipPercent: z.number().min(0).max(100).default(0),
|
|
50
|
-
total: z.number().min(0).max(1e12).default(0),
|
|
51
|
-
}),
|
|
75
|
+
props: BillSplitProps,
|
|
52
76
|
},
|
|
53
77
|
bookmark: {
|
|
54
|
-
description: 'Display, edit, and retain a web bookmark. No implicit metadata fetch.',
|
|
55
78
|
exportName: 'Bookmark',
|
|
56
|
-
props:
|
|
57
|
-
note: z.string().max(10_000).default(''),
|
|
58
|
-
title: title(),
|
|
59
|
-
url: webAddress(),
|
|
60
|
-
}),
|
|
61
|
-
storeSchema: store({
|
|
62
|
-
note: replacement(z.string().max(10_000).default('')),
|
|
63
|
-
title: replacement(z.string().max(160).default('')),
|
|
64
|
-
url: replacement(webAddress().nullable().default(null)),
|
|
65
|
-
}),
|
|
79
|
+
props: BookmarkProps,
|
|
66
80
|
},
|
|
67
81
|
budget: {
|
|
68
|
-
description:
|
|
69
|
-
'Track spending against category limits for one budget period. No bank connection or payments.',
|
|
70
82
|
exportName: 'Budget',
|
|
71
|
-
props:
|
|
72
|
-
categories: identifiedList(
|
|
73
|
-
{ label: z.string().min(1).max(80), limit: z.number().positive().max(1e12) },
|
|
74
|
-
12
|
|
75
|
-
),
|
|
76
|
-
currency: currency(),
|
|
77
|
-
title: title('Budget'),
|
|
78
|
-
}),
|
|
79
|
-
storeSchema: entries(entryPrefixes.budget, z.number().min(0).max(1e12), {}),
|
|
83
|
+
props: BudgetProps,
|
|
80
84
|
},
|
|
81
85
|
calculator: {
|
|
82
|
-
description:
|
|
83
|
-
'A persistent keypad calculator with chained arithmetic, decimals, sign, percent, and repeated equals. Supports +, -, *, /. No executable expression strings.',
|
|
84
86
|
exportName: 'Calculator',
|
|
85
|
-
props:
|
|
86
|
-
left: z.number().default(0),
|
|
87
|
-
operator: z.enum(['+', '-', '*', '/']).default('+'),
|
|
88
|
-
right: z.number().default(0),
|
|
89
|
-
title: title('Calculate'),
|
|
90
|
-
}),
|
|
91
|
-
storeSchema: store({
|
|
92
|
-
calculation: z
|
|
93
|
-
.object({
|
|
94
|
-
entry: z
|
|
95
|
-
.string()
|
|
96
|
-
.max(40)
|
|
97
|
-
.regex(/^(?:-?\d+(?:\.\d*)?(?:e[+-]?\d+)?|Error)$/),
|
|
98
|
-
left: z.number(),
|
|
99
|
-
operator: z.enum(['+', '-', '*', '/']),
|
|
100
|
-
overwrite: z.boolean(),
|
|
101
|
-
phase: z.enum(['left', 'operator', 'right', 'result', 'error']),
|
|
102
|
-
right: z.number(),
|
|
103
|
-
})
|
|
104
|
-
.refine(
|
|
105
|
-
calculation =>
|
|
106
|
-
calculation.phase === 'error'
|
|
107
|
-
? calculation.entry === 'Error'
|
|
108
|
-
: calculation.entry !== 'Error' &&
|
|
109
|
-
Number.isFinite(Number(calculation.entry)),
|
|
110
|
-
'Calculator entry must match its phase and represent a finite number.'
|
|
111
|
-
)
|
|
112
|
-
.default({
|
|
113
|
-
entry: '0',
|
|
114
|
-
left: 0,
|
|
115
|
-
operator: '+',
|
|
116
|
-
overwrite: false,
|
|
117
|
-
phase: 'left',
|
|
118
|
-
right: 0,
|
|
119
|
-
}),
|
|
120
|
-
}),
|
|
87
|
+
props: CalculatorProps,
|
|
121
88
|
},
|
|
122
89
|
checklist: {
|
|
123
|
-
description:
|
|
124
|
-
'A persistent checklist with independent completion and progress. No external actions.',
|
|
125
90
|
exportName: 'Checklist',
|
|
126
|
-
props:
|
|
127
|
-
items: identifiedList({ label: z.string().min(1).max(500) }, 100),
|
|
128
|
-
title: title(),
|
|
129
|
-
}),
|
|
130
|
-
storeSchema: entries(entryPrefixes.checklist, z.boolean(), {}),
|
|
91
|
+
props: ChecklistProps,
|
|
131
92
|
},
|
|
132
93
|
colorPalette: {
|
|
133
|
-
description: 'Choose and retain an sRGB color and display matching shades.',
|
|
134
94
|
exportName: 'ColorPalette',
|
|
135
|
-
props:
|
|
136
|
-
color: z.string().regex(/^#[\da-fA-F]{6}$/),
|
|
137
|
-
title: title('Palette'),
|
|
138
|
-
}),
|
|
139
|
-
storeSchema: store({
|
|
140
|
-
color: replacement(
|
|
141
|
-
z
|
|
142
|
-
.string()
|
|
143
|
-
.regex(/^#[\da-fA-F]{6}$/)
|
|
144
|
-
.default('#6366f1')
|
|
145
|
-
),
|
|
146
|
-
}),
|
|
95
|
+
props: ColorPaletteProps,
|
|
147
96
|
},
|
|
148
97
|
contact: {
|
|
149
|
-
description:
|
|
150
|
-
'Display, edit, and retain a contact. Does not insert into the address book.',
|
|
151
98
|
exportName: 'Contact',
|
|
152
|
-
props:
|
|
153
|
-
email: z.email().optional(),
|
|
154
|
-
name: z.string().min(1).max(160),
|
|
155
|
-
phone: z.string().min(1).max(80).optional(),
|
|
156
|
-
}),
|
|
157
|
-
storeSchema: store({
|
|
158
|
-
email: replacement(z.email().nullable().default(null)),
|
|
159
|
-
name: replacement(z.string().max(160).default('')),
|
|
160
|
-
phone: replacement(z.string().min(1).max(80).nullable().default(null)),
|
|
161
|
-
}),
|
|
99
|
+
props: ContactProps,
|
|
162
100
|
},
|
|
163
101
|
countdown: {
|
|
164
|
-
description:
|
|
165
|
-
'Count down to an explicit instant. Resolve missing dates before instantiation.',
|
|
166
102
|
exportName: 'Countdown',
|
|
167
|
-
props:
|
|
168
|
-
target: z.iso.datetime({ offset: true }),
|
|
169
|
-
timeZone: timeZone().default('UTC'),
|
|
170
|
-
title: title(),
|
|
171
|
-
}),
|
|
172
|
-
storeSchema: store({
|
|
173
|
-
target: replacement(z.iso.datetime({ offset: true }).nullable().default(null)),
|
|
174
|
-
}),
|
|
103
|
+
props: CountdownProps,
|
|
175
104
|
},
|
|
176
105
|
event: {
|
|
177
|
-
description:
|
|
178
|
-
'Save and edit event details in the app. Does not create a calendar event.',
|
|
179
106
|
exportName: 'Event',
|
|
180
|
-
props:
|
|
181
|
-
location: z.string().max(500).default(''),
|
|
182
|
-
startsAt: z.iso.datetime({ offset: true }).nullable().default(null),
|
|
183
|
-
timeZone: timeZone().default('UTC'),
|
|
184
|
-
title: title(),
|
|
185
|
-
}),
|
|
186
|
-
storeSchema: store({
|
|
187
|
-
location: replacement(z.string().max(500).default('')),
|
|
188
|
-
startsAt: replacement(z.iso.datetime({ offset: true }).nullable().default(null)),
|
|
189
|
-
title: replacement(z.string().max(160).default('')),
|
|
190
|
-
}),
|
|
107
|
+
props: EventProps,
|
|
191
108
|
},
|
|
192
109
|
expense: {
|
|
193
|
-
description:
|
|
194
|
-
'Edit and retain one expense. No payments, bank connection, or exchange-rate lookup.',
|
|
195
110
|
exportName: 'Expense',
|
|
196
|
-
props:
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}),
|
|
202
|
-
storeSchema: store({
|
|
203
|
-
amount: z.number().min(0).max(1e12).default(0),
|
|
204
|
-
category: replacement(z.string().max(80).default('Other')),
|
|
205
|
-
title: replacement(z.string().max(160).default('')),
|
|
206
|
-
}),
|
|
111
|
+
props: ExpenseProps,
|
|
112
|
+
},
|
|
113
|
+
fortune: {
|
|
114
|
+
exportName: 'Fortune',
|
|
115
|
+
props: FortuneProps,
|
|
207
116
|
},
|
|
208
117
|
goal: {
|
|
209
|
-
description:
|
|
210
|
-
'A personal goal with editable progress, target, and a fixed increment. Not a distributed counter.',
|
|
211
118
|
exportName: 'Goal',
|
|
212
|
-
props:
|
|
213
|
-
progress: z.number().min(0).max(1e12).default(0),
|
|
214
|
-
step: z.number().positive().max(1e9).default(1),
|
|
215
|
-
target: z.number().positive().max(1e12),
|
|
216
|
-
title: title(),
|
|
217
|
-
unit: z.string().max(40).default(''),
|
|
218
|
-
}),
|
|
219
|
-
storeSchema: store({ progress: z.number().min(0).default(0) }),
|
|
119
|
+
props: GoalProps,
|
|
220
120
|
},
|
|
221
121
|
habit: {
|
|
222
|
-
description:
|
|
223
|
-
'Track a habit by local date and edit its weekday schedule. No notifications.',
|
|
224
122
|
exportName: 'Habit',
|
|
225
|
-
props:
|
|
226
|
-
timeZone: timeZone().default('UTC'),
|
|
227
|
-
title: title(),
|
|
228
|
-
weekdays: weekdays(),
|
|
229
|
-
}),
|
|
230
|
-
storeSchema: entries(entryPrefixes.habit, z.boolean(), { weekdays: weekdays() }),
|
|
123
|
+
props: HabitProps,
|
|
231
124
|
},
|
|
232
125
|
ledger: {
|
|
233
|
-
description:
|
|
234
|
-
'A running tab of shared costs between two people, split evenly, with settle up. No payments.',
|
|
235
126
|
exportName: 'Ledger',
|
|
236
|
-
props:
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
storeSchema: store({
|
|
242
|
-
entries: z
|
|
243
|
-
.array(
|
|
244
|
-
z.strictObject({
|
|
245
|
-
amount: z.number().positive().max(1e12),
|
|
246
|
-
id: itemId(),
|
|
247
|
-
label: z.string().max(160),
|
|
248
|
-
paidBy: itemId(),
|
|
249
|
-
})
|
|
250
|
-
)
|
|
251
|
-
.max(200)
|
|
252
|
-
.default([]),
|
|
253
|
-
}),
|
|
127
|
+
props: LedgerProps,
|
|
128
|
+
},
|
|
129
|
+
lesson: {
|
|
130
|
+
exportName: 'Lesson',
|
|
131
|
+
props: LessonProps,
|
|
254
132
|
},
|
|
255
133
|
note: {
|
|
256
|
-
description: 'An editable persistent note. Plain text; no HTML or code execution.',
|
|
257
134
|
exportName: 'Note',
|
|
258
|
-
props:
|
|
259
|
-
body: z.string().max(20_000),
|
|
260
|
-
title: z.string().max(160),
|
|
261
|
-
}),
|
|
262
|
-
storeSchema: store({
|
|
263
|
-
body: replacement(z.string().max(20_000).default('')),
|
|
264
|
-
title: replacement(z.string().max(160).default('')),
|
|
265
|
-
}),
|
|
135
|
+
props: NoteProps,
|
|
266
136
|
},
|
|
267
137
|
poll: {
|
|
268
138
|
exportName: 'Poll',
|
|
269
|
-
|
|
270
|
-
'Cast or change a vote and derive totals from votes. Shared voting only when explicitly requested.',
|
|
271
|
-
props: featureProps({
|
|
272
|
-
options: identifiedList({ label: z.string().min(1).max(160) }, 12, 2),
|
|
273
|
-
question: z.string().min(1).max(500),
|
|
274
|
-
shared: z.boolean().default(false),
|
|
275
|
-
}),
|
|
276
|
-
// Each vote_<voter> holds an option id.
|
|
277
|
-
storeSchema: entries(entryPrefixes.poll, itemId(), {}),
|
|
139
|
+
props: PollProps,
|
|
278
140
|
},
|
|
279
141
|
randomPicker: {
|
|
280
|
-
description:
|
|
281
|
-
'Flip a coin, roll a die, or pick from a bounded integer range or list. Retains the last result.',
|
|
282
142
|
exportName: 'RandomPicker',
|
|
283
|
-
props:
|
|
284
|
-
featureProps({ mode: z.literal('coin'), title: title('Pick one') }),
|
|
285
|
-
featureProps({ mode: z.literal('dice'), title: title('Pick one') }),
|
|
286
|
-
featureProps({
|
|
287
|
-
maximum: z.number().int().min(-1e9).max(1e9),
|
|
288
|
-
minimum: z.number().int().min(-1e9).max(1e9),
|
|
289
|
-
mode: z.literal('range'),
|
|
290
|
-
title: title('Pick one'),
|
|
291
|
-
}).refine(value => value.minimum <= value.maximum, {
|
|
292
|
-
message: 'Minimum cannot exceed maximum.',
|
|
293
|
-
path: ['maximum'],
|
|
294
|
-
}),
|
|
295
|
-
featureProps({
|
|
296
|
-
mode: z.literal('list'),
|
|
297
|
-
options: z.array(z.string().min(1).max(160)).min(1).max(100),
|
|
298
|
-
title: title('Pick one'),
|
|
299
|
-
}),
|
|
300
|
-
]),
|
|
301
|
-
// The last pick, with the choices it was drawn from so a changed picker drops it.
|
|
302
|
-
storeSchema: store({
|
|
303
|
-
result: z
|
|
304
|
-
.strictObject({
|
|
305
|
-
domain: pickerDomain(),
|
|
306
|
-
value: z.union([z.number().int(), z.string().max(160)]),
|
|
307
|
-
})
|
|
308
|
-
.nullable()
|
|
309
|
-
.default(null),
|
|
310
|
-
}),
|
|
143
|
+
props: RandomPickerProps,
|
|
311
144
|
},
|
|
312
145
|
rating: {
|
|
313
|
-
description: 'Rate one thing from one to five stars and keep a short note about it.',
|
|
314
146
|
exportName: 'Rating',
|
|
315
|
-
props:
|
|
316
|
-
subject: z.string().min(1).max(160),
|
|
317
|
-
title: title('Your rating'),
|
|
318
|
-
}),
|
|
319
|
-
storeSchema: store({
|
|
320
|
-
note: replacement(z.string().max(2000).default('')),
|
|
321
|
-
stars: z.number().int().min(0).max(5).default(0),
|
|
322
|
-
}),
|
|
147
|
+
props: RatingProps,
|
|
323
148
|
},
|
|
324
149
|
recipe: {
|
|
325
|
-
description:
|
|
326
|
-
'Cook a recipe whose steps follow the Recipe Graph Format (rgf/0-draft): each step uses ingredients or earlier step outputs, waits on the steps in after, and may carry a duration, doneness cue, and attention. Ingredients carry a numeric amount and unit, and meta.servings is a number, so amounts scale with servings. Shows running timers, the current step, and the next few. No nutrition or shopping lookup.',
|
|
327
150
|
exportName: 'Recipe',
|
|
328
|
-
props:
|
|
329
|
-
ingredients: identifiedList(
|
|
330
|
-
{
|
|
331
|
-
amount: z.number().positive().max(1e6).optional(),
|
|
332
|
-
label: z.string().min(1).max(160),
|
|
333
|
-
notes: z.array(z.string().max(160)).max(10).optional(),
|
|
334
|
-
unit: z.string().max(40).optional(),
|
|
335
|
-
},
|
|
336
|
-
60
|
|
337
|
-
),
|
|
338
|
-
servings: z.number().int().min(1).max(100).optional(),
|
|
339
|
-
// Steps follow RGF (rgf/0-draft): uses, outputs, and after form the dependency graph.
|
|
340
|
-
steps: z
|
|
341
|
-
.array(
|
|
342
|
-
z.strictObject({
|
|
343
|
-
after: z.array(itemId()).max(60).optional(),
|
|
344
|
-
attention: z.enum(['active', 'passive']).optional(),
|
|
345
|
-
doneness: z.string().max(200).optional(),
|
|
346
|
-
duration: z
|
|
347
|
-
.strictObject({
|
|
348
|
-
maxMinutes: z.number().nonnegative().max(10_080).optional(),
|
|
349
|
-
minMinutes: z.number().nonnegative().max(10_080).optional(),
|
|
350
|
-
raw: z.string().min(1).max(80),
|
|
351
|
-
})
|
|
352
|
-
.refine(
|
|
353
|
-
duration =>
|
|
354
|
-
duration.minMinutes === undefined ||
|
|
355
|
-
duration.maxMinutes === undefined ||
|
|
356
|
-
duration.minMinutes <= duration.maxMinutes,
|
|
357
|
-
'minMinutes cannot exceed maxMinutes.'
|
|
358
|
-
)
|
|
359
|
-
.optional(),
|
|
360
|
-
equipment: z.array(z.string().min(1).max(160)).max(20).optional(),
|
|
361
|
-
id: itemId(),
|
|
362
|
-
instruction: z.string().min(1).max(500),
|
|
363
|
-
kind: z.enum(['setup', 'transform', 'wait', 'serve']).optional(),
|
|
364
|
-
label: z.string().max(80).optional(),
|
|
365
|
-
outputs: z
|
|
366
|
-
.array(z.strictObject({ id: itemId(), name: z.string().max(160).optional() }))
|
|
367
|
-
.max(10)
|
|
368
|
-
.optional(),
|
|
369
|
-
temperature: z.string().min(1).max(80).optional(),
|
|
370
|
-
uses: z
|
|
371
|
-
.array(
|
|
372
|
-
z.strictObject({
|
|
373
|
-
id: itemId(),
|
|
374
|
-
portion: z.string().max(80).optional(),
|
|
375
|
-
source: z.discriminatedUnion('kind', [
|
|
376
|
-
z.strictObject({ ingredientId: itemId(), kind: z.literal('ingredient') }),
|
|
377
|
-
z.strictObject({ kind: z.literal('output'), outputId: itemId() }),
|
|
378
|
-
]),
|
|
379
|
-
})
|
|
380
|
-
)
|
|
381
|
-
.max(30)
|
|
382
|
-
.default([]),
|
|
383
|
-
})
|
|
384
|
-
)
|
|
385
|
-
.min(1)
|
|
386
|
-
.max(60),
|
|
387
|
-
title: title(),
|
|
388
|
-
yield: z.string().max(160).optional(),
|
|
389
|
-
}).superRefine((recipe, context) => {
|
|
390
|
-
// Every edge points at an earlier step, so the graph is acyclic.
|
|
391
|
-
const ingredients = new Set(recipe.ingredients.map(ingredient => ingredient.id))
|
|
392
|
-
const steps = new Set<string>()
|
|
393
|
-
const outputs = new Set<string>()
|
|
394
|
-
for (const step of recipe.steps) {
|
|
395
|
-
const valid =
|
|
396
|
-
!steps.has(step.id) &&
|
|
397
|
-
(step.after ?? []).every(id => steps.has(id)) &&
|
|
398
|
-
step.uses.every(use =>
|
|
399
|
-
use.source.kind === 'ingredient'
|
|
400
|
-
? ingredients.has(use.source.ingredientId)
|
|
401
|
-
: outputs.has(use.source.outputId)
|
|
402
|
-
)
|
|
403
|
-
if (!valid) {
|
|
404
|
-
context.addIssue({
|
|
405
|
-
code: 'custom',
|
|
406
|
-
message: `Step ${step.id} needs a unique ID and can only use ingredients and earlier steps.`,
|
|
407
|
-
})
|
|
408
|
-
}
|
|
409
|
-
steps.add(step.id)
|
|
410
|
-
for (const output of step.outputs ?? []) {
|
|
411
|
-
if (outputs.has(output.id)) {
|
|
412
|
-
context.addIssue({ code: 'custom', message: 'Output IDs must be unique.' })
|
|
413
|
-
}
|
|
414
|
-
outputs.add(output.id)
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
}),
|
|
418
|
-
// Each step_<id> holds whether the step is done and when its timer ends.
|
|
419
|
-
storeSchema: entries(
|
|
420
|
-
entryPrefixes.recipe,
|
|
421
|
-
z.strictObject({ done: z.boolean(), endsAt: z.number().nullable() }),
|
|
422
|
-
{
|
|
423
|
-
cooking: z.boolean().default(false),
|
|
424
|
-
servings: z.number().int().min(1).max(100).default(1),
|
|
425
|
-
}
|
|
426
|
-
),
|
|
151
|
+
props: RecipeProps,
|
|
427
152
|
},
|
|
428
153
|
reminder: {
|
|
429
|
-
description:
|
|
430
|
-
'Complete, reopen, and edit an in-app reminder. Does not schedule notifications.',
|
|
431
154
|
exportName: 'Reminder',
|
|
432
|
-
props:
|
|
433
|
-
dueAt: z.iso.datetime({ offset: true }).nullable().default(null),
|
|
434
|
-
recurrence: z.enum(['none', 'daily', 'weekly']).default('none'),
|
|
435
|
-
timeZone: timeZone().optional(),
|
|
436
|
-
title: z.string().min(1).max(500),
|
|
437
|
-
}),
|
|
438
|
-
storeSchema: store({
|
|
439
|
-
completedAt: z.number().nullable().default(null),
|
|
440
|
-
dueAt: replacement(z.iso.datetime({ offset: true }).nullable().default(null)),
|
|
441
|
-
title: replacement(z.string().max(500).default('')),
|
|
442
|
-
}),
|
|
155
|
+
props: ReminderProps,
|
|
443
156
|
},
|
|
444
157
|
rotation: {
|
|
445
|
-
description:
|
|
446
|
-
'Take turns through a fixed group in order and pass the turn on when done.',
|
|
447
158
|
exportName: 'Rotation',
|
|
448
|
-
props:
|
|
449
|
-
people: identifiedList({ label: z.string().min(1).max(80) }, 20, 2),
|
|
450
|
-
task: z.string().min(1).max(160),
|
|
451
|
-
title: title('Whose turn'),
|
|
452
|
-
}),
|
|
453
|
-
// The person whose turn it is; null means the first person.
|
|
454
|
-
storeSchema: store({
|
|
455
|
-
completed: z.number().int().min(0).default(0),
|
|
456
|
-
turn: itemId().nullable().default(null),
|
|
457
|
-
}),
|
|
159
|
+
props: RotationProps,
|
|
458
160
|
},
|
|
459
161
|
scoreboard: {
|
|
460
|
-
description:
|
|
461
|
-
'Keep score for a few players with a fixed step. Not a distributed counter or a league.',
|
|
462
162
|
exportName: 'Scoreboard',
|
|
463
|
-
props:
|
|
464
|
-
players: identifiedList({ label: z.string().min(1).max(80) }, 12, 2),
|
|
465
|
-
step: z.number().int().positive().max(1000).default(1),
|
|
466
|
-
title: title('Scores'),
|
|
467
|
-
}),
|
|
468
|
-
storeSchema: entries(entryPrefixes.scoreboard, z.number().int(), {}),
|
|
163
|
+
props: ScoreboardProps,
|
|
469
164
|
},
|
|
470
165
|
shoppingList: {
|
|
471
|
-
description:
|
|
472
|
-
'Check items off a shopping list with optional prices and a running cart total. No ordering.',
|
|
473
166
|
exportName: 'ShoppingList',
|
|
474
|
-
props:
|
|
475
|
-
currency: currency(),
|
|
476
|
-
items: identifiedList(
|
|
477
|
-
{
|
|
478
|
-
label: z.string().min(1).max(160),
|
|
479
|
-
price: z.number().min(0).max(1e9).optional(),
|
|
480
|
-
quantity: z.number().int().min(1).max(999).default(1),
|
|
481
|
-
},
|
|
482
|
-
100
|
|
483
|
-
),
|
|
484
|
-
title: title('Shopping list'),
|
|
485
|
-
}),
|
|
486
|
-
storeSchema: entries(entryPrefixes.shoppingList, z.boolean(), {}),
|
|
167
|
+
props: ShoppingListProps,
|
|
487
168
|
},
|
|
488
169
|
taskBoard: {
|
|
489
|
-
description:
|
|
490
|
-
'Move tasks between To do, Doing, and Done. No assignees, dates, or sync.',
|
|
491
170
|
exportName: 'TaskBoard',
|
|
492
|
-
props:
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
171
|
+
props: TaskBoardProps,
|
|
172
|
+
},
|
|
173
|
+
timeSince: {
|
|
174
|
+
exportName: 'TimeSince',
|
|
175
|
+
props: TimeSinceProps,
|
|
497
176
|
},
|
|
498
177
|
timeZone: {
|
|
499
|
-
description:
|
|
500
|
-
'Compare local times in named time zones, live or at an explicit instant.',
|
|
501
178
|
exportName: 'TimeZone',
|
|
502
|
-
props:
|
|
503
|
-
at: z.iso.datetime({ offset: true }).nullable().default(null),
|
|
504
|
-
title: title('World clock'),
|
|
505
|
-
zones: z.array(timeZone()).min(2).max(6),
|
|
506
|
-
}),
|
|
507
|
-
storeSchema: store({
|
|
508
|
-
at: replacement(z.iso.datetime({ offset: true }).nullable().default(null)),
|
|
509
|
-
}),
|
|
179
|
+
props: TimeZoneProps,
|
|
510
180
|
},
|
|
511
181
|
timer: {
|
|
512
|
-
description:
|
|
513
|
-
'Countdown, focus, break, or stopwatch. Start, pause, resume, reset; no background alarm.',
|
|
514
182
|
exportName: 'Timer',
|
|
515
|
-
props:
|
|
516
|
-
durationSeconds: z.number().int().min(1).max(604_800).default(300),
|
|
517
|
-
mode: z.enum(['countdown', 'focus', 'break', 'stopwatch']).default('countdown'),
|
|
518
|
-
title: title('Timer'),
|
|
519
|
-
}),
|
|
520
|
-
storeSchema: store({
|
|
521
|
-
elapsedSeconds: z.number().min(0).default(0),
|
|
522
|
-
startedAt: z.number().nullable().default(null),
|
|
523
|
-
}),
|
|
183
|
+
props: TimerProps,
|
|
524
184
|
},
|
|
525
185
|
trip: {
|
|
526
|
-
description: 'Edit and retain trip details. No bookings or itinerary retrieval.',
|
|
527
186
|
exportName: 'Trip',
|
|
528
|
-
props:
|
|
529
|
-
destination: z.string().min(1).max(160),
|
|
530
|
-
endDate: z.iso.date().nullable().default(null),
|
|
531
|
-
origin: z.string().min(1).max(160),
|
|
532
|
-
startDate: z.iso.date().nullable().default(null),
|
|
533
|
-
title: title('Trip'),
|
|
534
|
-
transport: z.enum(['car', 'train', 'plane', 'walk', 'other']).default('other'),
|
|
535
|
-
}).refine(
|
|
536
|
-
value => !value.startDate || !value.endDate || value.endDate >= value.startDate,
|
|
537
|
-
{
|
|
538
|
-
message: 'The trip cannot end before it starts.',
|
|
539
|
-
path: ['endDate'],
|
|
540
|
-
}
|
|
541
|
-
),
|
|
542
|
-
storeSchema: store({
|
|
543
|
-
destination: replacement(z.string().max(160).default('')),
|
|
544
|
-
endDate: replacement(z.iso.date().nullable().default(null)),
|
|
545
|
-
origin: replacement(z.string().max(160).default('')),
|
|
546
|
-
startDate: replacement(z.iso.date().nullable().default(null)),
|
|
547
|
-
}).refine(
|
|
548
|
-
value =>
|
|
549
|
-
!value.startDate.value ||
|
|
550
|
-
!value.endDate.value ||
|
|
551
|
-
value.endDate.value >= value.startDate.value,
|
|
552
|
-
'The trip cannot end before it starts.'
|
|
553
|
-
),
|
|
187
|
+
props: TripProps,
|
|
554
188
|
},
|
|
555
189
|
unitConverter: {
|
|
556
|
-
description:
|
|
557
|
-
'Convert compatible length, mass, or temperature units deterministically.',
|
|
558
190
|
exportName: 'UnitConverter',
|
|
559
|
-
props:
|
|
560
|
-
from: unit(),
|
|
561
|
-
title: title('Convert'),
|
|
562
|
-
to: unit(),
|
|
563
|
-
value: z.number(),
|
|
564
|
-
}).refine(
|
|
565
|
-
({ from, to }) => unitDefinitions[from].dimension === unitDefinitions[to].dimension,
|
|
566
|
-
{
|
|
567
|
-
message: 'Source and destination units must measure the same dimension.',
|
|
568
|
-
path: ['to'],
|
|
569
|
-
}
|
|
570
|
-
),
|
|
571
|
-
storeSchema: store({
|
|
572
|
-
from: replacement(unit().default('km')),
|
|
573
|
-
to: replacement(unit().default('mi')),
|
|
574
|
-
value: z.number().default(0),
|
|
575
|
-
}).refine(
|
|
576
|
-
({ from, to }) =>
|
|
577
|
-
unitDefinitions[from.value].dimension === unitDefinitions[to.value].dimension,
|
|
578
|
-
'Incompatible units.'
|
|
579
|
-
),
|
|
191
|
+
props: UnitConverterProps,
|
|
580
192
|
},
|
|
581
193
|
}
|
|
582
|
-
|
|
583
|
-
export type KowalskiComponent = keyof typeof kowalskiCatalog
|
|
584
|
-
export const kowalskiComponentSchema = z.enum([
|
|
585
|
-
'checklist',
|
|
586
|
-
'timer',
|
|
587
|
-
'habit',
|
|
588
|
-
'goal',
|
|
589
|
-
'poll',
|
|
590
|
-
'event',
|
|
591
|
-
'reminder',
|
|
592
|
-
'trip',
|
|
593
|
-
'countdown',
|
|
594
|
-
'timeZone',
|
|
595
|
-
'colorPalette',
|
|
596
|
-
'billSplit',
|
|
597
|
-
'expense',
|
|
598
|
-
'unitConverter',
|
|
599
|
-
'calculator',
|
|
600
|
-
'randomPicker',
|
|
601
|
-
'contact',
|
|
602
|
-
'bookmark',
|
|
603
|
-
'note',
|
|
604
|
-
'budget',
|
|
605
|
-
'scoreboard',
|
|
606
|
-
'taskBoard',
|
|
607
|
-
'recipe',
|
|
608
|
-
'rotation',
|
|
609
|
-
'shoppingList',
|
|
610
|
-
'rating',
|
|
611
|
-
'ledger',
|
|
612
|
-
])
|
|
613
|
-
export type KowalskiInput<K extends KowalskiComponent> = z.input<
|
|
614
|
-
(typeof kowalskiCatalog)[K]['props']
|
|
615
|
-
>
|
|
616
|
-
export type KowalskiProps<K extends KowalskiComponent> = z.output<
|
|
617
|
-
(typeof kowalskiCatalog)[K]['props']
|
|
618
|
-
>
|
|
619
|
-
export type KowalskiState<K extends KowalskiComponent> = z.output<
|
|
620
|
-
(typeof kowalskiCatalog)[K]['storeSchema']
|
|
621
|
-
>
|
|
622
|
-
export type PickerDomain = NonNullable<KowalskiState<'randomPicker'>['result']>['domain']
|
|
623
|
-
export type Weekday = (typeof weekdayNames)[number]
|
|
624
|
-
|
|
625
|
-
export const pollVoterSchema = z.object({
|
|
626
|
-
configuration: z.string().default(''),
|
|
627
|
-
voter: z.string().min(1),
|
|
628
|
-
})
|
|
629
|
-
|
|
630
|
-
export const webAddressOptions = {
|
|
631
|
-
max_allowed_length: 2048,
|
|
632
|
-
protocols: ['http', 'https'],
|
|
633
|
-
require_host: true,
|
|
634
|
-
require_protocol: true,
|
|
635
|
-
require_tld: false,
|
|
636
|
-
require_valid_protocol: true,
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
/** SI relationships; temperature offsets are applied before scaling. */
|
|
640
|
-
export const unitDefinitions = {
|
|
641
|
-
c: { dimension: 'temperature', factor: 1, offset: 0 },
|
|
642
|
-
f: { dimension: 'temperature', factor: 5 / 9, offset: -32 },
|
|
643
|
-
ft: { dimension: 'length', factor: 0.3048, offset: 0 },
|
|
644
|
-
g: { dimension: 'mass', factor: 0.001, offset: 0 },
|
|
645
|
-
k: { dimension: 'temperature', factor: 1, offset: -273.15 },
|
|
646
|
-
kg: { dimension: 'mass', factor: 1, offset: 0 },
|
|
647
|
-
km: { dimension: 'length', factor: 1000, offset: 0 },
|
|
648
|
-
lb: { dimension: 'mass', factor: 0.45359237, offset: 0 },
|
|
649
|
-
m: { dimension: 'length', factor: 1, offset: 0 },
|
|
650
|
-
mi: { dimension: 'length', factor: 1609.344, offset: 0 },
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
function featureProps<Shape extends z.ZodRawShape>(shape: Shape) {
|
|
654
|
-
return z.strictObject({
|
|
655
|
-
id: kowalskiFeatureId,
|
|
656
|
-
revision: z.number().int().min(0).default(0),
|
|
657
|
-
scope: kowalskiScope,
|
|
658
|
-
...shape,
|
|
659
|
-
})
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
function currency() {
|
|
663
|
-
return z
|
|
664
|
-
.string()
|
|
665
|
-
.regex(/^[A-Z]{3}$/)
|
|
666
|
-
.default('USD')
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
/**
|
|
670
|
-
* Per-item state as top-level `<prefix><id>` fields, which Quantum patches independently.
|
|
671
|
-
* The template-literal record types them by prefix, so they never collide with the named
|
|
672
|
-
* fields; any other key is rejected.
|
|
673
|
-
*/
|
|
674
|
-
function entries<
|
|
675
|
-
Prefix extends string,
|
|
676
|
-
Value extends z.ZodType,
|
|
677
|
-
Shape extends z.ZodRawShape,
|
|
678
|
-
>(prefix: Prefix, value: Value, shape: Shape) {
|
|
679
|
-
const named = store(shape)
|
|
680
|
-
const keys = new Set(Object.keys(named.shape))
|
|
681
|
-
return z
|
|
682
|
-
.intersection(named.loose(), z.looseRecord(z.templateLiteral([prefix, z.string()]), value))
|
|
683
|
-
.refine(
|
|
684
|
-
state => Object.keys(state).every(key => keys.has(key) || key.startsWith(prefix)),
|
|
685
|
-
`Item fields must start with ${prefix}.`
|
|
686
|
-
)
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
/** Items with required stable ids, which key their saved state. */
|
|
690
|
-
function identifiedList<Shape extends z.ZodRawShape>(shape: Shape, max: number, min = 1) {
|
|
691
|
-
return z
|
|
692
|
-
.array(z.strictObject(shape).extend({ id: itemId() }))
|
|
693
|
-
.min(min)
|
|
694
|
-
.max(max)
|
|
695
|
-
.refine(uniqueIds, 'IDs must be unique.')
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
/** Free-form ids; they key Quantum state, so __proto__ is out. */
|
|
699
|
-
function itemId() {
|
|
700
|
-
return z
|
|
701
|
-
.string()
|
|
702
|
-
.min(1)
|
|
703
|
-
.max(80)
|
|
704
|
-
.refine(id => id !== '__proto__')
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
/**
|
|
708
|
-
* The choices a pick was drawn from. A plain union of strict variants (anyOf in JSON
|
|
709
|
-
* Schema) stays representable in the generated Quantum store source; oneOf does not.
|
|
710
|
-
*/
|
|
711
|
-
function pickerDomain() {
|
|
712
|
-
return z.union([
|
|
713
|
-
z.strictObject({ mode: z.literal('coin') }),
|
|
714
|
-
z.strictObject({ mode: z.literal('dice') }),
|
|
715
|
-
z.strictObject({
|
|
716
|
-
maximum: z.number().int(),
|
|
717
|
-
minimum: z.number().int(),
|
|
718
|
-
mode: z.literal('range'),
|
|
719
|
-
}),
|
|
720
|
-
z.strictObject({
|
|
721
|
-
mode: z.literal('list'),
|
|
722
|
-
options: z.array(z.string().max(160)).max(100),
|
|
723
|
-
}),
|
|
724
|
-
])
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
function store<Shape extends z.ZodRawShape>(shape: Shape) {
|
|
728
|
-
return z.object({
|
|
729
|
-
configuration: z.record(z.string(), z.unknown()).nullable().default(null),
|
|
730
|
-
configurationRevision: z.number().int().min(0).default(0),
|
|
731
|
-
...shape,
|
|
732
|
-
})
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
/** A feature heading: never empty. */
|
|
736
|
-
function title(): z.ZodString
|
|
737
|
-
function title(fallback: string): z.ZodDefault<z.ZodString>
|
|
738
|
-
function title(fallback?: string) {
|
|
739
|
-
const schema = z.string().min(1).max(160)
|
|
740
|
-
return fallback === undefined ? schema : schema.default(fallback)
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
function uniqueIds(items: ReadonlyArray<object>) {
|
|
744
|
-
const ids = items.map(item => ('id' in item ? item.id : undefined))
|
|
745
|
-
return new Set(ids).size === ids.length
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
function unit() {
|
|
749
|
-
return z.enum(['m', 'km', 'mi', 'ft', 'kg', 'g', 'lb', 'c', 'f', 'k'])
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
function timeZone() {
|
|
753
|
-
return z
|
|
754
|
-
.string()
|
|
755
|
-
.max(80)
|
|
756
|
-
.refine(value => {
|
|
757
|
-
try {
|
|
758
|
-
new Intl.DateTimeFormat('en', { timeZone: value }).format(0)
|
|
759
|
-
return true
|
|
760
|
-
} catch {
|
|
761
|
-
return false
|
|
762
|
-
}
|
|
763
|
-
}, 'Use a valid IANA time zone.')
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
/** Scheduled days of the week, by name. */
|
|
767
|
-
function weekdays() {
|
|
768
|
-
return z
|
|
769
|
-
.array(z.enum(weekdayNames))
|
|
770
|
-
.max(7)
|
|
771
|
-
.default([...weekdayNames])
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
function webAddress() {
|
|
775
|
-
return z
|
|
776
|
-
.string()
|
|
777
|
-
.max(2048)
|
|
778
|
-
.refine(
|
|
779
|
-
value => isURL(value, webAddressOptions),
|
|
780
|
-
'Use a valid HTTP or HTTPS address.'
|
|
781
|
-
)
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
/** Catalog fields are whole-value replacements, not collaborative text insertions. */
|
|
785
|
-
function replacement<Schema extends z.ZodType>(schema: Schema) {
|
|
786
|
-
return z.object({ value: schema }).default(() => ({ value: schema.parse(undefined) }))
|
|
787
|
-
}
|