@overcrow/mcp 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +90 -2
- package/dist/audit/index.js +103 -0
- package/dist/audit/lexer.js +417 -0
- package/dist/audit/project.js +200 -0
- package/dist/audit/rules.js +661 -0
- package/dist/bootstrap/download.js +229 -0
- package/dist/bootstrap/install.js +280 -0
- package/dist/bootstrap/pin.js +85 -0
- package/dist/bootstrap/pin.json +119 -0
- package/dist/bootstrap/zip.js +258 -0
- package/dist/cli.js +200 -0
- package/dist/confine.js +244 -0
- package/dist/content/docs/en/cli.md +353 -0
- package/dist/content/docs/en/dev-channel.md +130 -0
- package/dist/content/docs/en/elements.md +469 -0
- package/dist/content/docs/en/forms.md +328 -0
- package/dist/content/docs/en/guide.md +253 -0
- package/dist/content/docs/en/index.md +85 -0
- package/dist/content/docs/en/limits.md +241 -0
- package/dist/content/docs/en/logic.md +446 -0
- package/dist/content/docs/en/manifest.md +381 -0
- package/dist/content/docs/en/mcp.md +165 -0
- package/dist/content/docs/en/package.md +131 -0
- package/dist/content/docs/en/publishing.md +162 -0
- package/dist/content/docs/en/reference.md +55 -0
- package/dist/content/docs/en/result-shapes.md +332 -0
- package/dist/content/docs/en/sdk.md +295 -0
- package/dist/content/docs/en/security.md +115 -0
- package/dist/content/docs/en/service-reference.md +344 -0
- package/dist/content/docs/en/services.md +517 -0
- package/dist/content/docs/en/style-properties.md +270 -0
- package/dist/content/docs/en/style.md +266 -0
- package/dist/content/docs/en/testing.md +400 -0
- package/dist/content/docs/en/view.md +338 -0
- package/dist/content/docs/en/widgets.md +76 -0
- package/dist/content/docs/fr/cli.md +367 -0
- package/dist/content/docs/fr/dev-channel.md +140 -0
- package/dist/content/docs/fr/elements.md +475 -0
- package/dist/content/docs/fr/forms.md +341 -0
- package/dist/content/docs/fr/guide.md +264 -0
- package/dist/content/docs/fr/index.md +90 -0
- package/dist/content/docs/fr/limits.md +244 -0
- package/dist/content/docs/fr/logic.md +461 -0
- package/dist/content/docs/fr/manifest.md +392 -0
- package/dist/content/docs/fr/mcp.md +173 -0
- package/dist/content/docs/fr/package.md +139 -0
- package/dist/content/docs/fr/publishing.md +172 -0
- package/dist/content/docs/fr/reference.md +59 -0
- package/dist/content/docs/fr/result-shapes.md +333 -0
- package/dist/content/docs/fr/sdk.md +301 -0
- package/dist/content/docs/fr/security.md +129 -0
- package/dist/content/docs/fr/service-reference.md +346 -0
- package/dist/content/docs/fr/services.md +540 -0
- package/dist/content/docs/fr/style-properties.md +272 -0
- package/dist/content/docs/fr/style.md +281 -0
- package/dist/content/docs/fr/testing.md +417 -0
- package/dist/content/docs/fr/view.md +352 -0
- package/dist/content/docs/fr/widgets.md +81 -0
- package/dist/content/examples/clock/LICENSE +21 -0
- package/dist/content/examples/clock/README.md +75 -0
- package/dist/content/examples/clock/listing.json +19 -0
- package/dist/content/examples/clock/locales/en.json +4 -0
- package/dist/content/examples/clock/locales/fr.json +4 -0
- package/dist/content/examples/clock/logic.ts +85 -0
- package/dist/content/examples/clock/manifest.json +44 -0
- package/dist/content/examples/clock/package.json +16 -0
- package/dist/content/examples/clock/style.ocss +26 -0
- package/dist/content/examples/clock/tests/hidden.scenario.json +68 -0
- package/dist/content/examples/clock/tests/load-logic.mjs +22 -0
- package/dist/content/examples/clock/tests/logic.test.mjs +89 -0
- package/dist/content/examples/clock/tests/options.scenario.json +108 -0
- package/dist/content/examples/clock/tests/preview.scenario.json +25 -0
- package/dist/content/examples/clock/tests/render.scenario.json +94 -0
- package/dist/content/examples/clock/tests/summer-time.scenario.json +74 -0
- package/dist/content/examples/clock/tests/ticks.scenario.json +120 -0
- package/dist/content/examples/clock/tsconfig.json +16 -0
- package/dist/content/examples/clock/view.ocml +8 -0
- package/dist/content/examples/countdown/LICENSE +20 -0
- package/dist/content/examples/countdown/listing.json +10 -0
- package/dist/content/examples/countdown/locales/en.json +15 -0
- package/dist/content/examples/countdown/locales/fr.json +15 -0
- package/dist/content/examples/countdown/logic.ts +179 -0
- package/dist/content/examples/countdown/manifest.json +34 -0
- package/dist/content/examples/countdown/package.json +15 -0
- package/dist/content/examples/countdown/style.ocss +94 -0
- package/dist/content/examples/countdown/tsconfig.json +16 -0
- package/dist/content/examples/countdown/view.ocml +42 -0
- package/dist/content/examples/fps/LICENSE +21 -0
- package/dist/content/examples/fps/README.md +64 -0
- package/dist/content/examples/fps/listing.json +19 -0
- package/dist/content/examples/fps/locales/en.json +11 -0
- package/dist/content/examples/fps/locales/fr.json +11 -0
- package/dist/content/examples/fps/logic.ts +64 -0
- package/dist/content/examples/fps/manifest.json +30 -0
- package/dist/content/examples/fps/package.json +16 -0
- package/dist/content/examples/fps/style.ocss +31 -0
- package/dist/content/examples/fps/tests/label.scenario.json +63 -0
- package/dist/content/examples/fps/tests/load-logic.mjs +22 -0
- package/dist/content/examples/fps/tests/logic.test.mjs +60 -0
- package/dist/content/examples/fps/tests/preview.scenario.json +29 -0
- package/dist/content/examples/fps/tests/refused.scenario.json +20 -0
- package/dist/content/examples/fps/tests/render.scenario.json +96 -0
- package/dist/content/examples/fps/tests/stale.scenario.json +91 -0
- package/dist/content/examples/fps/tests/unavailable.scenario.json +111 -0
- package/dist/content/examples/fps/tsconfig.json +16 -0
- package/dist/content/examples/fps/view.ocml +11 -0
- package/dist/content/examples/media/LICENSE +21 -0
- package/dist/content/examples/media/README.md +147 -0
- package/dist/content/examples/media/listing.json +19 -0
- package/dist/content/examples/media/locales/en.json +11 -0
- package/dist/content/examples/media/locales/fr.json +11 -0
- package/dist/content/examples/media/logic.ts +191 -0
- package/dist/content/examples/media/manifest.json +35 -0
- package/dist/content/examples/media/package.json +16 -0
- package/dist/content/examples/media/style.ocss +148 -0
- package/dist/content/examples/media/tests/covers.scenario.json +144 -0
- package/dist/content/examples/media/tests/gesture.scenario.json +173 -0
- package/dist/content/examples/media/tests/load-logic.mjs +22 -0
- package/dist/content/examples/media/tests/logic.test.mjs +176 -0
- package/dist/content/examples/media/tests/marquee.scenario.json +127 -0
- package/dist/content/examples/media/tests/preview.scenario.json +52 -0
- package/dist/content/examples/media/tests/read-only.scenario.json +53 -0
- package/dist/content/examples/media/tests/refused.scenario.json +22 -0
- package/dist/content/examples/media/tests/refused.test.mjs +31 -0
- package/dist/content/examples/media/tests/render.scenario.json +136 -0
- package/dist/content/examples/media/tests/states.scenario.json +257 -0
- package/dist/content/examples/media/tests/unavailable.scenario.json +120 -0
- package/dist/content/examples/media/tsconfig.json +16 -0
- package/dist/content/examples/media/view.ocml +41 -0
- package/dist/content/examples/notes/LICENSE +21 -0
- package/dist/content/examples/notes/README.md +219 -0
- package/dist/content/examples/notes/listing.json +19 -0
- package/dist/content/examples/notes/locales/en.json +25 -0
- package/dist/content/examples/notes/locales/fr.json +25 -0
- package/dist/content/examples/notes/logic.ts +799 -0
- package/dist/content/examples/notes/manifest.json +40 -0
- package/dist/content/examples/notes/package.json +16 -0
- package/dist/content/examples/notes/style.ocss +469 -0
- package/dist/content/examples/notes/tests/checks.scenario.json +237 -0
- package/dist/content/examples/notes/tests/create.scenario.json +260 -0
- package/dist/content/examples/notes/tests/delete.scenario.json +342 -0
- package/dist/content/examples/notes/tests/drafts.scenario.json +714 -0
- package/dist/content/examples/notes/tests/editor.scenario.json +232 -0
- package/dist/content/examples/notes/tests/frame.scenario.json +93 -0
- package/dist/content/examples/notes/tests/interactive.scenario.json +344 -0
- package/dist/content/examples/notes/tests/limits.scenario.json +1351 -0
- package/dist/content/examples/notes/tests/load-logic.mjs +22 -0
- package/dist/content/examples/notes/tests/logic.test.mjs +514 -0
- package/dist/content/examples/notes/tests/preview.scenario.json +99 -0
- package/dist/content/examples/notes/tests/read-only.scenario.json +105 -0
- package/dist/content/examples/notes/tests/refused.scenario.json +33 -0
- package/dist/content/examples/notes/tests/save.scenario.json +378 -0
- package/dist/content/examples/notes/tests/states.scenario.json +640 -0
- package/dist/content/examples/notes/tests/typing.scenario.json +562 -0
- package/dist/content/examples/notes/tests/unavailable.scenario.json +246 -0
- package/dist/content/examples/notes/tsconfig.json +16 -0
- package/dist/content/examples/notes/view.ocml +154 -0
- package/dist/content/examples/performance/LICENSE +21 -0
- package/dist/content/examples/performance/README.md +134 -0
- package/dist/content/examples/performance/listing.json +19 -0
- package/dist/content/examples/performance/locales/en.json +20 -0
- package/dist/content/examples/performance/locales/fr.json +20 -0
- package/dist/content/examples/performance/logic.ts +210 -0
- package/dist/content/examples/performance/manifest.json +83 -0
- package/dist/content/examples/performance/package.json +16 -0
- package/dist/content/examples/performance/style.ocss +75 -0
- package/dist/content/examples/performance/tests/fahrenheit.scenario.json +110 -0
- package/dist/content/examples/performance/tests/horizontal.scenario.json +96 -0
- package/dist/content/examples/performance/tests/load-logic.mjs +22 -0
- package/dist/content/examples/performance/tests/logic.test.mjs +226 -0
- package/dist/content/examples/performance/tests/menu.scenario.json +170 -0
- package/dist/content/examples/performance/tests/no-fps-source.scenario.json +47 -0
- package/dist/content/examples/performance/tests/preview.scenario.json +45 -0
- package/dist/content/examples/performance/tests/refused.scenario.json +20 -0
- package/dist/content/examples/performance/tests/refused.test.mjs +19 -0
- package/dist/content/examples/performance/tests/region.scenario.json +89 -0
- package/dist/content/examples/performance/tests/render.scenario.json +112 -0
- package/dist/content/examples/performance/tests/sources.scenario.json +151 -0
- package/dist/content/examples/performance/tests/stale.scenario.json +111 -0
- package/dist/content/examples/performance/tests/telemetry-only.scenario.json +44 -0
- package/dist/content/examples/performance/tests/thresholds.scenario.json +147 -0
- package/dist/content/examples/performance/tests/waiting.scenario.json +105 -0
- package/dist/content/examples/performance/tsconfig.json +16 -0
- package/dist/content/examples/performance/view.ocml +18 -0
- package/dist/content/examples/playervox-journal/LICENSE +21 -0
- package/dist/content/examples/playervox-journal/README.md +150 -0
- package/dist/content/examples/playervox-journal/listing.json +19 -0
- package/dist/content/examples/playervox-journal/locales/en.json +25 -0
- package/dist/content/examples/playervox-journal/locales/fr.json +25 -0
- package/dist/content/examples/playervox-journal/logic.ts +556 -0
- package/dist/content/examples/playervox-journal/manifest.json +19 -0
- package/dist/content/examples/playervox-journal/package.json +16 -0
- package/dist/content/examples/playervox-journal/style.ocss +142 -0
- package/dist/content/examples/playervox-journal/tests/changes.scenario.json +482 -0
- package/dist/content/examples/playervox-journal/tests/delete.scenario.json +432 -0
- package/dist/content/examples/playervox-journal/tests/frame.scenario.json +169 -0
- package/dist/content/examples/playervox-journal/tests/load-logic.mjs +22 -0
- package/dist/content/examples/playervox-journal/tests/logic.test.mjs +349 -0
- package/dist/content/examples/playervox-journal/tests/paging.scenario.json +428 -0
- package/dist/content/examples/playervox-journal/tests/preview.scenario.json +184 -0
- package/dist/content/examples/playervox-journal/tests/read-only.scenario.json +157 -0
- package/dist/content/examples/playervox-journal/tests/refused.scenario.json +39 -0
- package/dist/content/examples/playervox-journal/tests/scale.scenario.json +286 -0
- package/dist/content/examples/playervox-journal/tests/signed-out.scenario.json +134 -0
- package/dist/content/examples/playervox-journal/tests/states.scenario.json +741 -0
- package/dist/content/examples/playervox-journal/tests/unavailable.scenario.json +183 -0
- package/dist/content/examples/playervox-journal/tsconfig.json +16 -0
- package/dist/content/examples/playervox-journal/view.ocml +52 -0
- package/dist/content/examples/playervox-rating/LICENSE +21 -0
- package/dist/content/examples/playervox-rating/README.md +166 -0
- package/dist/content/examples/playervox-rating/listing.json +19 -0
- package/dist/content/examples/playervox-rating/locales/en.json +35 -0
- package/dist/content/examples/playervox-rating/locales/fr.json +35 -0
- package/dist/content/examples/playervox-rating/logic.ts +581 -0
- package/dist/content/examples/playervox-rating/manifest.json +19 -0
- package/dist/content/examples/playervox-rating/package.json +16 -0
- package/dist/content/examples/playervox-rating/style.ocss +333 -0
- package/dist/content/examples/playervox-rating/tests/account.scenario.json +125 -0
- package/dist/content/examples/playervox-rating/tests/bounds.scenario.json +73 -0
- package/dist/content/examples/playervox-rating/tests/draft.scenario.json +199 -0
- package/dist/content/examples/playervox-rating/tests/form.scenario.json +142 -0
- package/dist/content/examples/playervox-rating/tests/load-logic.mjs +22 -0
- package/dist/content/examples/playervox-rating/tests/logic.test.mjs +346 -0
- package/dist/content/examples/playervox-rating/tests/offline.scenario.json +142 -0
- package/dist/content/examples/playervox-rating/tests/preview.scenario.json +44 -0
- package/dist/content/examples/playervox-rating/tests/publish-keyboard.scenario.json +221 -0
- package/dist/content/examples/playervox-rating/tests/publish-pointer.scenario.json +314 -0
- package/dist/content/examples/playervox-rating/tests/read-only.scenario.json +70 -0
- package/dist/content/examples/playervox-rating/tests/refused.scenario.json +45 -0
- package/dist/content/examples/playervox-rating/tests/states.scenario.json +362 -0
- package/dist/content/examples/playervox-rating/tsconfig.json +16 -0
- package/dist/content/examples/playervox-rating/view.ocml +62 -0
- package/dist/content/examples/playervox-reviews/LICENSE +21 -0
- package/dist/content/examples/playervox-reviews/README.md +194 -0
- package/dist/content/examples/playervox-reviews/listing.json +19 -0
- package/dist/content/examples/playervox-reviews/locales/en.json +32 -0
- package/dist/content/examples/playervox-reviews/locales/fr.json +32 -0
- package/dist/content/examples/playervox-reviews/logic.ts +822 -0
- package/dist/content/examples/playervox-reviews/manifest.json +30 -0
- package/dist/content/examples/playervox-reviews/package.json +16 -0
- package/dist/content/examples/playervox-reviews/style.ocss +260 -0
- package/dist/content/examples/playervox-reviews/tests/account.scenario.json +249 -0
- package/dist/content/examples/playervox-reviews/tests/bounds.scenario.json +336 -0
- package/dist/content/examples/playervox-reviews/tests/changes.scenario.json +515 -0
- package/dist/content/examples/playervox-reviews/tests/filter.scenario.json +400 -0
- package/dist/content/examples/playervox-reviews/tests/frame.scenario.json +185 -0
- package/dist/content/examples/playervox-reviews/tests/keyboard.scenario.json +188 -0
- package/dist/content/examples/playervox-reviews/tests/load-logic.mjs +22 -0
- package/dist/content/examples/playervox-reviews/tests/logic.test.mjs +559 -0
- package/dist/content/examples/playervox-reviews/tests/offline-start.scenario.json +152 -0
- package/dist/content/examples/playervox-reviews/tests/offline.scenario.json +311 -0
- package/dist/content/examples/playervox-reviews/tests/paging.scenario.json +497 -0
- package/dist/content/examples/playervox-reviews/tests/preview.scenario.json +286 -0
- package/dist/content/examples/playervox-reviews/tests/reading.scenario.json +591 -0
- package/dist/content/examples/playervox-reviews/tests/refused.scenario.json +54 -0
- package/dist/content/examples/playervox-reviews/tests/scale.scenario.json +303 -0
- package/dist/content/examples/playervox-reviews/tests/states.scenario.json +700 -0
- package/dist/content/examples/playervox-reviews/tests/unavailable.scenario.json +192 -0
- package/dist/content/examples/playervox-reviews/tsconfig.json +16 -0
- package/dist/content/examples/playervox-reviews/view.ocml +110 -0
- package/dist/content/examples/playervox-score/LICENSE +21 -0
- package/dist/content/examples/playervox-score/README.md +131 -0
- package/dist/content/examples/playervox-score/listing.json +19 -0
- package/dist/content/examples/playervox-score/locales/en.json +23 -0
- package/dist/content/examples/playervox-score/locales/fr.json +23 -0
- package/dist/content/examples/playervox-score/logic.ts +430 -0
- package/dist/content/examples/playervox-score/manifest.json +47 -0
- package/dist/content/examples/playervox-score/package.json +16 -0
- package/dist/content/examples/playervox-score/style.ocss +247 -0
- package/dist/content/examples/playervox-score/tests/grades.scenario.json +279 -0
- package/dist/content/examples/playervox-score/tests/load-logic.mjs +22 -0
- package/dist/content/examples/playervox-score/tests/logic.test.mjs +229 -0
- package/dist/content/examples/playervox-score/tests/options.scenario.json +302 -0
- package/dist/content/examples/playervox-score/tests/preview.scenario.json +68 -0
- package/dist/content/examples/playervox-score/tests/pulse.scenario.json +157 -0
- package/dist/content/examples/playervox-score/tests/refused.scenario.json +21 -0
- package/dist/content/examples/playervox-score/tests/signed-out.scenario.json +46 -0
- package/dist/content/examples/playervox-score/tests/states.scenario.json +450 -0
- package/dist/content/examples/playervox-score/tests/unavailable.scenario.json +84 -0
- package/dist/content/examples/playervox-score/tsconfig.json +16 -0
- package/dist/content/examples/playervox-score/view.ocml +51 -0
- package/dist/content/examples/session/LICENSE +21 -0
- package/dist/content/examples/session/README.md +57 -0
- package/dist/content/examples/session/listing.json +19 -0
- package/dist/content/examples/session/locales/en.json +3 -0
- package/dist/content/examples/session/locales/fr.json +3 -0
- package/dist/content/examples/session/logic.ts +26 -0
- package/dist/content/examples/session/manifest.json +19 -0
- package/dist/content/examples/session/package.json +16 -0
- package/dist/content/examples/session/style.ocss +16 -0
- package/dist/content/examples/session/tests/hidden.scenario.json +45 -0
- package/dist/content/examples/session/tests/load-logic.mjs +22 -0
- package/dist/content/examples/session/tests/logic.test.mjs +37 -0
- package/dist/content/examples/session/tests/preview.scenario.json +28 -0
- package/dist/content/examples/session/tests/refused.scenario.json +20 -0
- package/dist/content/examples/session/tests/refused.test.mjs +16 -0
- package/dist/content/examples/session/tests/render.scenario.json +95 -0
- package/dist/content/examples/session/tests/ticks.scenario.json +139 -0
- package/dist/content/examples/session/tests/unknown.scenario.json +37 -0
- package/dist/content/examples/session/tsconfig.json +16 -0
- package/dist/content/examples/session/view.ocml +11 -0
- package/dist/content/examples/stopwatch/LICENSE +21 -0
- package/dist/content/examples/stopwatch/README.md +99 -0
- package/dist/content/examples/stopwatch/listing.json +19 -0
- package/dist/content/examples/stopwatch/locales/en.json +8 -0
- package/dist/content/examples/stopwatch/locales/fr.json +8 -0
- package/dist/content/examples/stopwatch/logic.ts +93 -0
- package/dist/content/examples/stopwatch/manifest.json +19 -0
- package/dist/content/examples/stopwatch/package.json +16 -0
- package/dist/content/examples/stopwatch/style.ocss +54 -0
- package/dist/content/examples/stopwatch/tests/errors.scenario.json +121 -0
- package/dist/content/examples/stopwatch/tests/gesture.scenario.json +154 -0
- package/dist/content/examples/stopwatch/tests/hidden.scenario.json +57 -0
- package/dist/content/examples/stopwatch/tests/hundredths.scenario.json +173 -0
- package/dist/content/examples/stopwatch/tests/load-logic.mjs +22 -0
- package/dist/content/examples/stopwatch/tests/logic.test.mjs +99 -0
- package/dist/content/examples/stopwatch/tests/preview.scenario.json +36 -0
- package/dist/content/examples/stopwatch/tests/read-only.scenario.json +42 -0
- package/dist/content/examples/stopwatch/tests/read-only.test.mjs +18 -0
- package/dist/content/examples/stopwatch/tests/refused.scenario.json +22 -0
- package/dist/content/examples/stopwatch/tests/refused.test.mjs +18 -0
- package/dist/content/examples/stopwatch/tests/render.scenario.json +105 -0
- package/dist/content/examples/stopwatch/tests/states.scenario.json +246 -0
- package/dist/content/examples/stopwatch/tests/unknown.scenario.json +40 -0
- package/dist/content/examples/stopwatch/tsconfig.json +16 -0
- package/dist/content/examples/stopwatch/view.ocml +29 -0
- package/dist/content/examples/twitch-chat/LICENSE +21 -0
- package/dist/content/examples/twitch-chat/README.md +283 -0
- package/dist/content/examples/twitch-chat/listing.json +19 -0
- package/dist/content/examples/twitch-chat/locales/en.json +52 -0
- package/dist/content/examples/twitch-chat/locales/fr.json +52 -0
- package/dist/content/examples/twitch-chat/logic.ts +887 -0
- package/dist/content/examples/twitch-chat/manifest.json +33 -0
- package/dist/content/examples/twitch-chat/package.json +16 -0
- package/dist/content/examples/twitch-chat/style.ocss +544 -0
- package/dist/content/examples/twitch-chat/tests/account.scenario.json +325 -0
- package/dist/content/examples/twitch-chat/tests/burst.scenario.json +1866 -0
- package/dist/content/examples/twitch-chat/tests/channel-refused.scenario.json +372 -0
- package/dist/content/examples/twitch-chat/tests/channel.scenario.json +480 -0
- package/dist/content/examples/twitch-chat/tests/draft.scenario.json +279 -0
- package/dist/content/examples/twitch-chat/tests/fade.scenario.json +269 -0
- package/dist/content/examples/twitch-chat/tests/failures.scenario.json +420 -0
- package/dist/content/examples/twitch-chat/tests/favorites.scenario.json +376 -0
- package/dist/content/examples/twitch-chat/tests/frame.scenario.json +152 -0
- package/dist/content/examples/twitch-chat/tests/lifetime.scenario.json +186 -0
- package/dist/content/examples/twitch-chat/tests/load-logic.mjs +22 -0
- package/dist/content/examples/twitch-chat/tests/logic.test.mjs +1053 -0
- package/dist/content/examples/twitch-chat/tests/passive.scenario.json +536 -0
- package/dist/content/examples/twitch-chat/tests/preview.scenario.json +147 -0
- package/dist/content/examples/twitch-chat/tests/read-only.scenario.json +202 -0
- package/dist/content/examples/twitch-chat/tests/read-only.test.mjs +63 -0
- package/dist/content/examples/twitch-chat/tests/refused.scenario.json +65 -0
- package/dist/content/examples/twitch-chat/tests/refused.test.mjs +43 -0
- package/dist/content/examples/twitch-chat/tests/render.scenario.json +347 -0
- package/dist/content/examples/twitch-chat/tests/reply.scenario.json +384 -0
- package/dist/content/examples/twitch-chat/tests/send-refused.scenario.json +383 -0
- package/dist/content/examples/twitch-chat/tests/send.scenario.json +300 -0
- package/dist/content/examples/twitch-chat/tests/states.scenario.json +455 -0
- package/dist/content/examples/twitch-chat/tests/unavailable.scenario.json +256 -0
- package/dist/content/examples/twitch-chat/tests/unread.scenario.json +997 -0
- package/dist/content/examples/twitch-chat/tsconfig.json +16 -0
- package/dist/content/examples/twitch-chat/view.ocml +141 -0
- package/dist/content/examples/warframe-market/LICENSE +21 -0
- package/dist/content/examples/warframe-market/README.md +176 -0
- package/dist/content/examples/warframe-market/listing.json +19 -0
- package/dist/content/examples/warframe-market/locales/en.json +44 -0
- package/dist/content/examples/warframe-market/locales/fr.json +44 -0
- package/dist/content/examples/warframe-market/logic.ts +1265 -0
- package/dist/content/examples/warframe-market/manifest.json +92 -0
- package/dist/content/examples/warframe-market/package.json +16 -0
- package/dist/content/examples/warframe-market/style.ocss +422 -0
- package/dist/content/examples/warframe-market/tests/bounds.scenario.json +60 -0
- package/dist/content/examples/warframe-market/tests/cached.scenario.json +70 -0
- package/dist/content/examples/warframe-market/tests/detail.scenario.json +251 -0
- package/dist/content/examples/warframe-market/tests/errors.scenario.json +105 -0
- package/dist/content/examples/warframe-market/tests/fixtures.json +295 -0
- package/dist/content/examples/warframe-market/tests/load-logic.mjs +22 -0
- package/dist/content/examples/warframe-market/tests/logic.test.mjs +505 -0
- package/dist/content/examples/warframe-market/tests/no-clipboard.scenario.json +104 -0
- package/dist/content/examples/warframe-market/tests/passive.scenario.json +87 -0
- package/dist/content/examples/warframe-market/tests/preview.scenario.json +146 -0
- package/dist/content/examples/warframe-market/tests/refresh.scenario.json +56 -0
- package/dist/content/examples/warframe-market/tests/refused.scenario.json +74 -0
- package/dist/content/examples/warframe-market/tests/render.scenario.json +210 -0
- package/dist/content/examples/warframe-market/tests/search.scenario.json +189 -0
- package/dist/content/examples/warframe-market/tests/unavailable.scenario.json +54 -0
- package/dist/content/examples/warframe-market/tsconfig.json +16 -0
- package/dist/content/examples/warframe-market/view.ocml +116 -0
- package/dist/content/examples/weather/LICENSE +20 -0
- package/dist/content/examples/weather/listing.json +10 -0
- package/dist/content/examples/weather/locales/en.json +9 -0
- package/dist/content/examples/weather/locales/fr.json +9 -0
- package/dist/content/examples/weather/logic.ts +62 -0
- package/dist/content/examples/weather/manifest.json +51 -0
- package/dist/content/examples/weather/package.json +15 -0
- package/dist/content/examples/weather/style.ocss +29 -0
- package/dist/content/examples/weather/tsconfig.json +16 -0
- package/dist/content/examples/weather/view.ocml +12 -0
- package/dist/content/index.json +3601 -0
- package/dist/content/reference/errors.json +1712 -0
- package/dist/content/reference/limits.json +1154 -0
- package/dist/content/reference/manifest.md +223 -0
- package/dist/content/reference/permissions.json +413 -0
- package/dist/content/templates/blank/locales/en.json +3 -0
- package/dist/content/templates/blank/locales/fr.json +3 -0
- package/dist/content/templates/blank/logic.ts +7 -0
- package/dist/content/templates/blank/manifest.json +16 -0
- package/dist/content/templates/blank/style.ocss +10 -0
- package/dist/content/templates/blank/tests/example.scenario.json +10 -0
- package/dist/content/templates/blank/view.ocml +6 -0
- package/dist/content/templates/chart/locales/en.json +3 -0
- package/dist/content/templates/chart/locales/fr.json +3 -0
- package/dist/content/templates/chart/logic.ts +27 -0
- package/dist/content/templates/chart/manifest.json +16 -0
- package/dist/content/templates/chart/style.ocss +27 -0
- package/dist/content/templates/chart/tests/example.scenario.json +10 -0
- package/dist/content/templates/chart/view.ocml +10 -0
- package/dist/content/templates/counter/locales/en.json +4 -0
- package/dist/content/templates/counter/locales/fr.json +4 -0
- package/dist/content/templates/counter/logic.ts +20 -0
- package/dist/content/templates/counter/manifest.json +16 -0
- package/dist/content/templates/counter/style.ocss +26 -0
- package/dist/content/templates/counter/tests/example.scenario.json +11 -0
- package/dist/content/templates/counter/view.ocml +13 -0
- package/dist/content/templates/list/locales/en.json +8 -0
- package/dist/content/templates/list/locales/fr.json +8 -0
- package/dist/content/templates/list/logic.ts +35 -0
- package/dist/content/templates/list/manifest.json +16 -0
- package/dist/content/templates/list/style.ocss +42 -0
- package/dist/content/templates/list/tests/example.scenario.json +10 -0
- package/dist/content/templates/list/view.ocml +17 -0
- package/dist/content/templates/shared/LICENSE +20 -0
- package/dist/content/templates/shared/package.json +14 -0
- package/dist/content/templates/shared/tsconfig.json +16 -0
- package/dist/content.js +68 -0
- package/dist/env.js +156 -0
- package/dist/fingerprint.js +32 -0
- package/dist/ids.js +27 -0
- package/dist/index.js +82 -0
- package/dist/knowledge.js +222 -0
- package/dist/npm.js +149 -0
- package/dist/prompts.js +47 -0
- package/dist/resources.js +82 -0
- package/dist/run.js +120 -0
- package/dist/server.js +43 -0
- package/dist/session.js +205 -0
- package/dist/sources.js +218 -0
- package/dist/text.js +80 -0
- package/dist/texts.js +44 -0
- package/dist/tools/audit.js +105 -0
- package/dist/tools/build.js +453 -0
- package/dist/tools/common.js +122 -0
- package/dist/tools/docs.js +196 -0
- package/dist/tools/preview.js +87 -0
- package/dist/tools/project.js +178 -0
- package/dist/tools/setup.js +146 -0
- package/dist/tools/submission.js +369 -0
- package/dist/version.js +3 -0
- package/npm-shrinkwrap.json +402 -0
- package/package.json +52 -4
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
# La vue
|
|
2
|
+
|
|
3
|
+
`view.ocml` décrit ce qu’affiche un widget PlayerVox OverCrow : un arbre
|
|
4
|
+
d’éléments, lié à l’état du widget par des expressions `{…}`. Il ressemble à
|
|
5
|
+
du HTML ou à du JSX, mais ce n’est ni l’un ni l’autre : le jeu d’éléments
|
|
6
|
+
est fermé, il n’y a pas de DOM et la vue ne contient aucun script. OverCrow
|
|
7
|
+
met en page et dessine l’arbre lui-même.
|
|
8
|
+
|
|
9
|
+
<!-- source: templates/list/view.ocml -->
|
|
10
|
+
```xml
|
|
11
|
+
<box class="checklist">
|
|
12
|
+
<text class="title">{t("title")}</text>
|
|
13
|
+
<list class="items" item-height="32">
|
|
14
|
+
<for each={state.items} as="item" key={item.id}>
|
|
15
|
+
<box class="row">
|
|
16
|
+
<checkbox label={item.text} checked={item.done} on:change={setDone(item.id, event.value)}/>
|
|
17
|
+
<text class={item.done ? "text done" : "text"}>{item.text}</text>
|
|
18
|
+
<button class="remove" label={t("remove")} on:activate={remove(item.id)}>
|
|
19
|
+
<icon name="x"/>
|
|
20
|
+
</button>
|
|
21
|
+
</box>
|
|
22
|
+
</for>
|
|
23
|
+
</list>
|
|
24
|
+
<text class="summary">{t("remaining", { count: remaining(state.items) })}</text>
|
|
25
|
+
</box>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
C’est le template de liste de tâches : un titre, une `list` défilante qui
|
|
29
|
+
répète une ligne par entrée, et un résumé. La logique exporte `setDone`,
|
|
30
|
+
`remove` et `remaining` ; `t` lit les messages de `locales/`.
|
|
31
|
+
|
|
32
|
+
La vue est compilée quand vous empaquetez le widget : `overcrow-widget check`
|
|
33
|
+
signale chaque erreur avec sa ligne et sa colonne. Un élément, un attribut ou
|
|
34
|
+
un événement inconnu est une erreur, jamais ignorée. Le fichier source
|
|
35
|
+
lui-même n’est pas livré.
|
|
36
|
+
|
|
37
|
+
## Balisage
|
|
38
|
+
|
|
39
|
+
- Le fichier est en UTF-8, sans marque d’ordre des octets.
|
|
40
|
+
- Le document est une liste de nœuds de premier niveau : des déclarations
|
|
41
|
+
`<component>` et les enfants de la racine du widget, qui est une `box`.
|
|
42
|
+
- Les éléments s’écrivent en minuscules : `<name …>…</name>` ou
|
|
43
|
+
`<name …/>`.
|
|
44
|
+
- La valeur d’un attribut est un texte entre guillemets (`"…"` ou `'…'`),
|
|
45
|
+
une expression (`{…}`), ou rien, ce qui vaut `true` : `<button submit>`.
|
|
46
|
+
Les attributs sont séparés par des blancs et ne se répètent jamais.
|
|
47
|
+
- Les commentaires s’écrivent `<!-- … -->`, sans `--` à l’intérieur.
|
|
48
|
+
- DOCTYPE, instructions de traitement, sections CDATA et espaces de noms
|
|
49
|
+
sont refusés.
|
|
50
|
+
|
|
51
|
+
Les entités sont `&` `<` `>` `"` `'` `{`
|
|
52
|
+
`}` ` `, ainsi que `&#…;` ou `&#x…;` pour tout caractère qui
|
|
53
|
+
n’est pas un caractère de contrôle. Un `{` ou un `}` littéral dans une
|
|
54
|
+
valeur entre guillemets, comme un `}` isolé dans du texte, est refusé :
|
|
55
|
+
écrivez `{` et `}`.
|
|
56
|
+
|
|
57
|
+
## Éléments
|
|
58
|
+
|
|
59
|
+
Chaque élément a un contenu fixe, un jeu d’attributs et les événements qu’il
|
|
60
|
+
peut envoyer. Les conteneurs (`box`, `scroll`, `list`, `form`, `popover`,
|
|
61
|
+
`button`) contiennent d’autres éléments ; `text` contient du texte et des
|
|
62
|
+
enfants en ligne ; les autres sont des feuilles qu’OverCrow dessine :
|
|
63
|
+
`icon`, `image`, `toggle`, `slider`, `field`, `chart`, `gauge`…
|
|
64
|
+
|
|
65
|
+
<!-- generated:element-list -->
|
|
66
|
+
| Élément | Signification |
|
|
67
|
+
| --- | --- |
|
|
68
|
+
| [`box`](elements.md#box) | Conteneur générique ; la mise en page flex ou grid vient du style. La racine de la vue est un `box`. |
|
|
69
|
+
| [`scroll`](elements.md#scroll) | Conteneur qui rogne son contenu et que l’hôte fait défiler à la molette, par glissement et au clavier. |
|
|
70
|
+
| [`list`](elements.md#list) | Liste à défilement vertical dont les enfants ne sont mis en page et peints que lorsqu’ils sont visibles. |
|
|
71
|
+
| [`text`](elements.md#text) | Bloc de texte avec retour à la ligne ; ses enfants en ligne suivent le texte (une ligne de chat avec des emotes). |
|
|
72
|
+
| [`span`](elements.md#span) | Portion de texte stylée à l’intérieur d’un `text`. |
|
|
73
|
+
| [`icon`](elements.md#icon) | Icône Lucide teintée par `color`, dimensionnée par `font-size` sauf si `width` et `height` sont définis. |
|
|
74
|
+
| [`image`](elements.md#image) | Image matricielle du paquet, ou image remise par un service (identifiant `asset:`) ; `object-fit` s’applique. |
|
|
75
|
+
| [`avatar`](elements.md#avatar) | Image ronde, avec un texte de remplacement tant que l’image manque ou n’a pas pu être chargée. |
|
|
76
|
+
| [`badge`](elements.md#badge) | Courte pastille de texte. |
|
|
77
|
+
| [`button`](elements.md#button) | Contrôle activable ; ses enfants (icône, texte) forment son contenu. |
|
|
78
|
+
| [`toggle`](elements.md#toggle) | Bascule activé/désactivé. |
|
|
79
|
+
| [`checkbox`](elements.md#checkbox) | Case à cocher (listes de tâches). |
|
|
80
|
+
| [`slider`](elements.md#slider) | Curseur sur un intervalle numérique ; le glissement est géré par l’hôte. |
|
|
81
|
+
| [`select`](elements.md#select) | Liste déroulante ; la liste ouverte est dessinée par l’hôte. |
|
|
82
|
+
| [`option`](elements.md#option) | Choix d’un `select` ; son texte est le libellé affiché. |
|
|
83
|
+
| [`field`](elements.md#field) | Champ de texte d’une ligne, édité par l’hôte, méthodes de saisie (IME) comprises. |
|
|
84
|
+
| [`textarea`](elements.md#textarea) | Champ de texte de plusieurs lignes, édité par l’hôte, méthodes de saisie (IME) comprises. |
|
|
85
|
+
| [`form`](elements.md#form) | Regroupe des contrôles nommés. Avec `intent`, la validation envoie leurs valeurs à un service d’écriture directement depuis l’hôte ; la logique du widget ne fournit jamais ce contenu. |
|
|
86
|
+
| [`elapsed`](elements.md#elapsed) | Durée affichée que l’hôte fait avancer à partir d’un repère donné par un service : un chronomètre qui tourne ne demande aucun travail à la logique. Stylé comme `text` ; repeint seulement quand le texte affiché change, au plus à 60 Hz, et jamais quand le widget est masqué. |
|
|
87
|
+
| [`progress`](elements.md#progress) | Barre de progression horizontale. |
|
|
88
|
+
| [`gauge`](elements.md#gauge) | Jauge en anneau ou en arc. |
|
|
89
|
+
| [`chart`](elements.md#chart) | Graphique en ligne, en aire, en barres ou sparkline, dessiné par l’hôte. |
|
|
90
|
+
| [`series`](elements.md#series) | Une série de données d’un `chart`, colorée par `color`. |
|
|
91
|
+
| [`separator`](elements.md#separator) | Filet de séparation entre deux groupes. |
|
|
92
|
+
| [`canvas`](elements.md#canvas) | Surface que l’hôte peint à partir de la dernière liste de commandes passée à `draw`. |
|
|
93
|
+
| [`popover`](elements.md#popover) | Panneau flottant ancré à un élément, dessiné au-dessus du contenu et rogné au cadre du widget (listes déroulantes, menus contextuels). |
|
|
94
|
+
<!-- /generated:element-list -->
|
|
95
|
+
|
|
96
|
+
[Éléments et attributs](elements.md) donne les attributs et les événements
|
|
97
|
+
de chacun.
|
|
98
|
+
|
|
99
|
+
## Texte
|
|
100
|
+
|
|
101
|
+
Le texte n’est admis que dans `text`, `span`, `badge` et `option`. Un `text`
|
|
102
|
+
contient soit du texte, soit des enfants en ligne (`span`, `icon`, `image`),
|
|
103
|
+
jamais les deux : pour styler un seul mot, placez chaque segment dans un
|
|
104
|
+
`span`.
|
|
105
|
+
|
|
106
|
+
<!-- source: widgets/performance/view.ocml -->
|
|
107
|
+
```xml
|
|
108
|
+
<text class={row.valueClass} label={row.name} tooltip={row.hint}><span>{row.value}</span><if test={row.unit != ""}><span class="unit">{row.unit}</span></if></text>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Les blancs suivent la règle de JSX :
|
|
112
|
+
|
|
113
|
+
- les tabulations deviennent des espaces ;
|
|
114
|
+
- un saut de ligne entre deux mots devient une espace ;
|
|
115
|
+
- un saut de ligne accolé à une balise ou à une expression disparaît avec
|
|
116
|
+
son indentation ;
|
|
117
|
+
- une suite de blancs accolée à une balise est supprimée ; entre deux
|
|
118
|
+
expressions sur la même ligne, elle est conservée.
|
|
119
|
+
|
|
120
|
+
Un saut de ligne avant une expression supprime donc l’espace qui la
|
|
121
|
+
précède : écrivez `you have {state.count} messages` sur une seule ligne pour
|
|
122
|
+
garder les deux espaces, ou écrivez ` ` là où il vous faut une espace
|
|
123
|
+
que la règle supprimerait.
|
|
124
|
+
|
|
125
|
+
## Attributs
|
|
126
|
+
|
|
127
|
+
Une valeur entre guillemets est convertie dans le type de l’attribut et
|
|
128
|
+
vérifiée à la compilation de la vue :
|
|
129
|
+
|
|
130
|
+
| Type | Valeur entre guillemets |
|
|
131
|
+
| --- | --- |
|
|
132
|
+
| booléen | `true` ou `false` ; l’attribut seul vaut `true` |
|
|
133
|
+
| entier | un entier décimal, sans zéro initial |
|
|
134
|
+
| nombre | un nombre décimal, sans exposant |
|
|
135
|
+
| liste de nombres | des nombres séparés par des espaces : `values="12 18.5 30"` |
|
|
136
|
+
| texte, identifiant | le texte lui-même |
|
|
137
|
+
| image | un fichier du paquet : `src="assets/logo.png"` |
|
|
138
|
+
|
|
139
|
+
`attr={expression}`, en revanche, lie l’attribut à une expression ; OverCrow
|
|
140
|
+
vérifie chaque valeur qu’envoie le widget. Les valeurs qui n’existent qu’à
|
|
141
|
+
l’exécution du widget, comme une image fournie par un service, doivent être
|
|
142
|
+
liées.
|
|
143
|
+
|
|
144
|
+
Cinq attributs existent sur tous les éléments :
|
|
145
|
+
|
|
146
|
+
<!-- generated:common-attributes -->
|
|
147
|
+
| Attribut | Type | Obligatoire | Signification |
|
|
148
|
+
| --- | --- | --- | --- |
|
|
149
|
+
| `class` | liste de classes | non | Classes de style : des noms distincts, séparés par une espace. |
|
|
150
|
+
| `ref` | nom de `ref` statique | non | Nom par lequel `draw` désigne ce `canvas` et par lequel un attribut tel que `anchor` d’un `popover` désigne cet élément. Statique, unique dans la vue, et interdit dans un `for` ou dans le corps d’un composant, où il nommerait plusieurs éléments. |
|
|
151
|
+
| `label` | texte ≤ 256 octets | non | Nom accessible ; obligatoire sur les contrôles qui ne montrent qu’une icône. |
|
|
152
|
+
| `tooltip` | texte ≤ 256 octets | non | Texte brut que l’hôte affiche au survol ou au focus. |
|
|
153
|
+
| `on` | noms d’événements triés | non | Événements transmis à la logique ; s’écrit `on:<event>` dans la vue. |
|
|
154
|
+
<!-- /generated:common-attributes -->
|
|
155
|
+
|
|
156
|
+
`class` est le point d’accroche du [style](style.md). `label` est le nom
|
|
157
|
+
accessible de l’élément : donnez-en un à chaque contrôle dont le contenu est
|
|
158
|
+
une icône.
|
|
159
|
+
|
|
160
|
+
### Nommer un élément : `ref`
|
|
161
|
+
|
|
162
|
+
`ref="name"` donne un nom à un élément. Ce nom sert à deux choses :
|
|
163
|
+
`draw(name, commands)` dessine dans le `canvas` de ce nom, et un `popover`
|
|
164
|
+
se place contre l’élément que nomme son `anchor`.
|
|
165
|
+
|
|
166
|
+
<!-- source: docs/content/examples/countdown/view.ocml -->
|
|
167
|
+
```xml
|
|
168
|
+
<box ref="panel" class="countdown" on:contextmenu={openMenu}>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
<!-- source: docs/content/examples/countdown/view.ocml -->
|
|
172
|
+
```xml
|
|
173
|
+
<popover anchor="panel" placement="pointer" open={state.menu} on:dismiss={closeMenu}>
|
|
174
|
+
<button class="menu-row" on:activate={resetRounds}>
|
|
175
|
+
<text class="menu-text">{t("reset-rounds")}</text>
|
|
176
|
+
</button>
|
|
177
|
+
</popover>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Un `ref` s’écrit toujours entre guillemets et il est unique dans la vue. Il
|
|
181
|
+
est refusé dans un `for` ou dans un composant, où il nommerait plusieurs
|
|
182
|
+
éléments.
|
|
183
|
+
|
|
184
|
+
## Événements
|
|
185
|
+
|
|
186
|
+
`on:event={handler}` demande à OverCrow d’envoyer à la logique un événement
|
|
187
|
+
de l’élément. Sans cela, le widget ignore tout de l’événement : OverCrow ne
|
|
188
|
+
lui signale ni les mouvements du pointeur ni les appuis de touches qu’il n’a
|
|
189
|
+
pas demandés.
|
|
190
|
+
|
|
191
|
+
Un gestionnaire s’écrit de deux façons :
|
|
192
|
+
|
|
193
|
+
- **le nom d’une fonction** exportée par la logique, appelée avec le détail
|
|
194
|
+
de l’événement : `on:activate={increment}` ;
|
|
195
|
+
- **un appel**, avec les arguments de votre choix ; `event` y désigne le
|
|
196
|
+
détail de l’événement : `on:change={setDone(item.id, event.value)}`.
|
|
197
|
+
|
|
198
|
+
<!-- source: templates/list/view.ocml -->
|
|
199
|
+
```xml
|
|
200
|
+
<checkbox label={item.text} checked={item.done} on:change={setDone(item.id, event.value)}/>
|
|
201
|
+
<text class={item.done ? "text done" : "text"}>{item.text}</text>
|
|
202
|
+
<button class="remove" label={t("remove")} on:activate={remove(item.id)}>
|
|
203
|
+
<icon name="x"/>
|
|
204
|
+
</button>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Les événements sont `activate`, `contextmenu`, `wheel`, `keydown`, `input`,
|
|
208
|
+
`change`, `submit`, `focus`, `blur`, `reachend`, `stick` et `dismiss` ;
|
|
209
|
+
[événements](elements.md#événements) décrit chacun d’eux et le détail qu’il
|
|
210
|
+
transporte, et chaque [élément](elements.md#éléments) liste ceux qu’il
|
|
211
|
+
envoie. Certains sont des actions de l’utilisateur, pendant lesquelles un
|
|
212
|
+
widget peut appeler un service protégé ; voir
|
|
213
|
+
[les appels qui demandent une action de l’utilisateur](services.md#les-appels-qui-demandent-une-action-de-lutilisateur).
|
|
214
|
+
Les widgets ne reçoivent d’entrées qu’en mode interactif d’OverCrow : en
|
|
215
|
+
mode passif, les clics les traversent et atteignent le jeu.
|
|
216
|
+
|
|
217
|
+
## Conditions, boucles et composants
|
|
218
|
+
|
|
219
|
+
<!-- generated:constructs -->
|
|
220
|
+
| Syntaxe | Signification |
|
|
221
|
+
| --- | --- |
|
|
222
|
+
| `{expr}` | Insère la valeur d’une expression dans du texte ou dans la valeur d’un attribut. |
|
|
223
|
+
| `<if test={expr}> … <else-if test={expr}> … <else>` | Sous-arbre conditionnel. |
|
|
224
|
+
| `<for each={expr} as="item" key={expr}>` | Répète un sous-arbre ; `key` est obligatoire et doit être unique parmi les éléments répétés. |
|
|
225
|
+
| `<component name="x" props="a b"> … <slot/> … </component>` | Composant local, avec ses propriétés déclarées et un emplacement (`slot`), utilisé sous la forme `<x a={…}>`. |
|
|
226
|
+
| `on:<event>={handler}` | Abonne l’élément à l’un de ses événements et nomme le gestionnaire de la logique. |
|
|
227
|
+
<!-- /generated:constructs -->
|
|
228
|
+
|
|
229
|
+
### `if`, `else-if`, `else`
|
|
230
|
+
|
|
231
|
+
<!-- source: widgets/stopwatch/view.ocml -->
|
|
232
|
+
```xml
|
|
233
|
+
<if test={state.stopwatch.running}>
|
|
234
|
+
<icon name="pause"/>
|
|
235
|
+
</if>
|
|
236
|
+
<else>
|
|
237
|
+
<icon name="play"/>
|
|
238
|
+
</else>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
`else-if` et `else` suivent directement un `if` : seuls des blancs et des
|
|
242
|
+
commentaires peuvent les en séparer.
|
|
243
|
+
|
|
244
|
+
### `for`
|
|
245
|
+
|
|
246
|
+
`for` répète ses enfants pour chaque entrée d’une liste. `each`, `as` et
|
|
247
|
+
`key` sont tous obligatoires, et la clé doit être unique parmi les entrées
|
|
248
|
+
répétées : c’est grâce à elle qu’OverCrow sait quelle ligne a bougé, est
|
|
249
|
+
apparue ou a disparu.
|
|
250
|
+
|
|
251
|
+
<!-- source: widgets/warframe-market/view.ocml -->
|
|
252
|
+
```xml
|
|
253
|
+
<for each={state.results} as="item" key={item.slug}>
|
|
254
|
+
<button class="result" label={item.name} on:activate={select(item.slug)}>
|
|
255
|
+
<text class="result-name">{item.name}</text>
|
|
256
|
+
<icon class="result-arrow" name="chevron-right"/>
|
|
257
|
+
</button>
|
|
258
|
+
</for>
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Pour une longue liste, placez le `for` dans un élément `list` : OverCrow ne
|
|
262
|
+
met en page et ne dessine que les lignes visibles.
|
|
263
|
+
|
|
264
|
+
### Composants
|
|
265
|
+
|
|
266
|
+
Un composant est un morceau de vue doté d’un nom et de propriétés déclarées,
|
|
267
|
+
à écrire une fois et à utiliser plusieurs fois. Il est local à la vue.
|
|
268
|
+
|
|
269
|
+
<!-- source: docs/content/examples/countdown/view.ocml -->
|
|
270
|
+
```xml
|
|
271
|
+
<component name="stat" props="name value">
|
|
272
|
+
<box class="stat">
|
|
273
|
+
<text class="stat-name">{name}</text>
|
|
274
|
+
<text class="stat-value">{value}</text>
|
|
275
|
+
</box>
|
|
276
|
+
</component>
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
<!-- source: docs/content/examples/countdown/view.ocml -->
|
|
280
|
+
```xml
|
|
281
|
+
<stat name={t("state")} value={stateText(state.running, state.remainingMs)}/>
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
- Les composants se déclarent au premier niveau, une seule fois chacun,
|
|
285
|
+
sous un nom qui n’est pas celui d’un élément.
|
|
286
|
+
- Le corps ne voit que ses propres propriétés, pas les noms visibles là où
|
|
287
|
+
le composant est utilisé. Passez-lui ce dont il a besoin.
|
|
288
|
+
- Une utilisation ne passe que des propriétés déclarées. Une propriété entre
|
|
289
|
+
guillemets est un texte ; liez-la (`value={5}`) pour tout autre type.
|
|
290
|
+
- Un corps peut contenir un seul `<slot/>`, où vont les enfants de chaque
|
|
291
|
+
utilisation.
|
|
292
|
+
- Un composant ne peut pas se contenir lui-même, et une utilisation
|
|
293
|
+
n’accepte pas de gestionnaires `on:` : placez-les sur des éléments du
|
|
294
|
+
corps.
|
|
295
|
+
|
|
296
|
+
`if`, `for` et les composants sont transparents pour les règles de contenu :
|
|
297
|
+
leurs enfants doivent convenir à l’élément qui les entoure.
|
|
298
|
+
|
|
299
|
+
## Expressions
|
|
300
|
+
|
|
301
|
+
Les expressions forment un sous-ensemble de JavaScript, réduit et strict :
|
|
302
|
+
|
|
303
|
+
- les littéraux : nombres (`0`, `12`, `1.5`), chaînes, `true`, `false`,
|
|
304
|
+
`null`, littéraux de tableau et d’objet ;
|
|
305
|
+
- les noms de la portée et leurs membres : `a.b`, `a?.b`, `a[i]`,
|
|
306
|
+
`a?.[i]` ;
|
|
307
|
+
- les opérateurs : `!`, `-` et `+` unaires, `* / %`, `+ -`, `< <= > >=`,
|
|
308
|
+
`== != === !==`, `&&`, `||`, `??`, et `a ? b : c`. `??` ne se combine pas
|
|
309
|
+
avec `&&` ou `||` sans parenthèses ;
|
|
310
|
+
- les appels de fonctions exportées par la logique, par leur nom seul :
|
|
311
|
+
`remaining(state.items)`. `t(key, params)` en fait partie.
|
|
312
|
+
|
|
313
|
+
Les noms de la portée sont `state`, les noms `as` des `for` englobants, les
|
|
314
|
+
propriétés du composant englobant, et `event` dans un gestionnaire. Un nom
|
|
315
|
+
ne peut pas en masquer un autre.
|
|
316
|
+
|
|
317
|
+
Il n’y a ni affectation, ni fonction fléchée ou littérale, ni `new`, ni
|
|
318
|
+
`this`, ni littéral de gabarit, ni expression régulière, ni appel de
|
|
319
|
+
méthode, ni globale : tout ce qui dépasse un calcul simple a sa place dans
|
|
320
|
+
une fonction de la logique. C’est ce qui permet de vérifier la vue : à
|
|
321
|
+
l’empaquetage du widget, chaque expression est compilée en une fonction de
|
|
322
|
+
`logic.js`, et la vue elle-même ne contient aucun code.
|
|
323
|
+
|
|
324
|
+
<!-- source: templates/list/view.ocml -->
|
|
325
|
+
```xml
|
|
326
|
+
<text class={item.done ? "text done" : "text"}>{item.text}</text>
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Les mots réservés de JavaScript, `constructor`, `prototype`, `eval`,
|
|
330
|
+
`undefined`, `globalThis`, `overcrow` et tout nom qui commence par `__` sont
|
|
331
|
+
refusés.
|
|
332
|
+
|
|
333
|
+
## Quand la vue est incorrecte
|
|
334
|
+
|
|
335
|
+
Chaque problème est un diagnostic de `overcrow-widget check`, doté d’un code
|
|
336
|
+
stable :
|
|
337
|
+
|
|
338
|
+
| Code | Problème |
|
|
339
|
+
| --- | --- |
|
|
340
|
+
| `view.syntax`, `view.encoding`, `view.size`, `view.invalid_entity` | Le fichier n’est pas un balisage bien formé. |
|
|
341
|
+
| `view.unknown_element`, `view.invalid_parent` | Un élément qui n’existe pas, ou placé là où il ne peut pas être. |
|
|
342
|
+
| `view.unknown_attribute`, `view.duplicate_attribute`, `view.invalid_attribute`, `view.missing_attribute` | Un attribut que l’élément n’a pas, écrit deux fois, de valeur incorrecte, ou obligatoire et absent. |
|
|
343
|
+
| `view.unknown_event`, `view.invalid_handler` | Un événement que l’élément n’envoie pas (ou posé sur l’utilisation d’un composant), ou un gestionnaire qui n’est ni un nom ni un appel. |
|
|
344
|
+
| `view.expression_syntax`, `view.expression_too_long`, `view.expression_too_deep`, `view.expression_too_many_entries` | Une expression hors du sous-ensemble ou de ses limites. |
|
|
345
|
+
| `view.reserved_name`, `view.unknown_name` | Un nom refusé, ou absent de la portée. |
|
|
346
|
+
| `view.invalid_text` | Du texte là où l’élément n’en accepte pas, ou mêlé à des enfants en ligne. |
|
|
347
|
+
| `view.invalid_component`, `view.recursive_component`, `view.invalid_slot`, `view.invalid_construct` | Un composant, un slot, un `if` ou un `for` qui enfreint ses règles. |
|
|
348
|
+
| `view.invalid_ref`, `view.unknown_ref` | Un `ref` qui n’est pas unique ou qui se trouve dans un `for`, ou un `anchor` qui n’en nomme aucun. |
|
|
349
|
+
| `view.missing_asset` | Une image statique absente de `assets/`. |
|
|
350
|
+
| `view.bound_value` | Un `value` sur un contrôle d’un formulaire lié à un intent d’écriture ; voir [les formulaires](forms.md#les-formulaires-qui-écrivent-des-données-de-lutilisateur). |
|
|
351
|
+
| `view.too_many_elements`, `view.too_many_components`, `view.too_many_children`, `view.too_many_expressions`, `view.too_deep` | Une [limite](limits.md) de la vue est dépassée. |
|
|
352
|
+
| `logic.missing_export` | La vue appelle une fonction que la logique n’exporte pas. |
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Widgets de référence
|
|
2
|
+
|
|
3
|
+
Les widgets intégrés de PlayerVox OverCrow sont des widgets ordinaires,
|
|
4
|
+
écrits avec le SDK public, empaquetés par `overcrow-widget` et publiés dans
|
|
5
|
+
le catalogue signé comme les vôtres. Leurs sources se trouvent dans
|
|
6
|
+
[`widgets/`](../../../widgets/), dans le dépôt public, sous licence MIT :
|
|
7
|
+
lisez-les, copiez-les et servez-vous-en comme point de départ.
|
|
8
|
+
|
|
9
|
+
<!-- generated:widgets -->
|
|
10
|
+
| Widget | Description | ID | Permissions | Sources |
|
|
11
|
+
| --- | --- | --- | --- | --- |
|
|
12
|
+
| **Horloge** | Affiche l’heure locale et, en option, la date, au format 24 heures. | `com.playervox.overcrow.clock` | aucune | [widgets/clock/](../../../widgets/clock/) |
|
|
13
|
+
| **FPS** | Affiche la fréquence d’images présentée par le jeu, quand l’hôte dispose d’une source. | `com.playervox.overcrow.fps` | `fps.read` | [widgets/fps/](../../../widgets/fps/) |
|
|
14
|
+
| **Média** | Le morceau que joue votre lecteur de musique, avec sa pochette, et les boutons précédent, lecture/pause et suivant en mode interactif. | `com.playervox.overcrow.media` | `media.read`, `media.control` | [widgets/media/](../../../widgets/media/) |
|
|
15
|
+
| **Notes** | Vos notes et listes de tâches par-dessus le jeu : jusqu’à huit notes, chacune avec un texte libre et une liste de tâches, les mêmes pour tous les jeux. Lisez-les en mode passif ; en mode interactif, choisissez, créez, supprimez et modifiez-les dans le widget, et cochez les éléments. Elles restent sur cet ordinateur. | `com.playervox.overcrow.notes` | `notes.read`, `notes.write` | [widgets/notes/](../../../widgets/notes/) |
|
|
16
|
+
| **Performances** | CPU et mémoire du jeu, et les températures que cet ordinateur expose. | `com.playervox.overcrow.performance` | `telemetry.read`, `fps.read` | [widgets/performance/](../../../widgets/performance/) |
|
|
17
|
+
| **Journal de sessions** | Les sessions de jeu terminées de votre jeu, de la plus récente à la plus ancienne : date, heure de début et durée, cinq par page. Enregistrées sur votre appareil sans compte, fusionnées avec votre journal PlayerVox si vous synchronisez. Supprimez une session après confirmation. | `com.playervox.overcrow.playervox.journal` | `journal.read`, `journal.delete` | [widgets/playervox-journal/](../../../widgets/playervox-journal/) |
|
|
18
|
+
| **Ma note** | Votre note PlayerVox du jeu Steam auquel vous jouez : son grade et son score, et en mode interactif trois critères et un avis facultatif à publier ou mettre à jour. Nécessite votre compte PlayerVox. | `com.playervox.overcrow.playervox.rating` | `playervox.rating.read`, `playervox.rating.write` | [widgets/playervox-rating/](../../../widgets/playervox-rating/) |
|
|
19
|
+
| **Avis des joueurs** | Ce que les joueurs de PlayerVox pensent du jeu auquel vous jouez : trois avis par page avec la note et le score de chaque joueur, dans votre langue quand une traduction existe. Limitez-les aux joueurs que vous suivez depuis le menu du widget. Nécessite votre compte PlayerVox. | `com.playervox.overcrow.playervox.reviews` | `playervox.reviews.read` | [widgets/playervox-reviews/](../../../widgets/playervox-reviews/) |
|
|
20
|
+
| **Note PlayerVox** | La note de la communauté PlayerVox pour votre jeu Steam, avec son score, son nombre de votes et trois critères. Sans compte ; le badge reste toujours visible. | `com.playervox.overcrow.playervox.score` | `playervox.score.read` | [widgets/playervox-score/](../../../widgets/playervox-score/) |
|
|
21
|
+
| **Session** | Affiche la durée de la session de jeu en cours. | `com.playervox.overcrow.session` | `session.read` | [widgets/session/](../../../widgets/session/) |
|
|
22
|
+
| **Chronomètre** | Un chronomètre au centième de seconde, démarré, mis en pause et réinitialisé par ses boutons ou les raccourcis de l’hôte. | `com.playervox.overcrow.stopwatch` | `stopwatch.read`, `stopwatch.control` | [widgets/stopwatch/](../../../widgets/stopwatch/) |
|
|
23
|
+
| **Chat Twitch** | Lisez et envoyez des messages dans le chat Twitch public de votre choix : vos chaînes favorites, l’historique défilant avec emotes et réponses en mode interactif, les derniers messages qui s’effacent en mode passif. Nécessite votre compte Twitch. | `com.playervox.overcrow.twitch.chat` | `twitch.chat.read`, `twitch.chat.compose` | [widgets/twitch-chat/](../../../widgets/twitch-chat/) |
|
|
24
|
+
| **Marché Warframe** | Recherche les objets PC publics dans un catalogue en cache, affiche les vendeurs et acheteurs en ligne d’un objet dans deux onglets et copie un message d’échange sur un clic. | `com.playervox.overcrow.warframe.market` | `network`, `storage`, `clipboardWrite` | [widgets/warframe-market/](../../../widgets/warframe-market/) |
|
|
25
|
+
<!-- /generated:widgets -->
|
|
26
|
+
|
|
27
|
+
## Ce que contient le dossier d’un widget
|
|
28
|
+
|
|
29
|
+
- les sources du paquet : `manifest.json`, `view.ocml`, `style.ocss`,
|
|
30
|
+
`logic.ts`, `locales/`, `LICENSE` ;
|
|
31
|
+
- `listing.json`, son texte pour la marketplace ;
|
|
32
|
+
- `assets/preview.png`, son aperçu dans la marketplace : l’image de son
|
|
33
|
+
scénario `preview`, cadrée et mise en scène par
|
|
34
|
+
`node scripts/compose-previews.mjs` ;
|
|
35
|
+
- `tests/` : les tests unitaires de la logique, et des scénarios avec leurs
|
|
36
|
+
images de référence dans les deux thèmes, les deux langues et deux
|
|
37
|
+
échelles, joués par `overcrow-widget test` dans le runtime headless
|
|
38
|
+
d’OverCrow ;
|
|
39
|
+
- `README.md` : ce qu’il affiche, son menu, ses permissions, son
|
|
40
|
+
fonctionnement et son coût.
|
|
41
|
+
|
|
42
|
+
## Ce que chacun montre
|
|
43
|
+
|
|
44
|
+
| Pour voir comment… | Lisez |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| se déclencher à chaque minute ou seconde de l’heure locale, suivre une option du menu | Horloge |
|
|
47
|
+
| s’abonner à un service et afficher une valeur manquante | FPS, Session |
|
|
48
|
+
| disposer une liste de valeurs en grille, masquer une ligne du menu que la machine ne peut pas alimenter | Performances |
|
|
49
|
+
| afficher une image fournie par OverCrow, relancer un abonnement qui s’est terminé | Média |
|
|
50
|
+
| commander un service sur une action de l’utilisateur, laisser OverCrow faire avancer une durée | Chronomètre |
|
|
51
|
+
| modifier du texte avec un formulaire lié à un intent d’écriture, conserver des brouillons | Notes, Ma note |
|
|
52
|
+
| dessiner sur un canvas | Note PlayerVox, Ma note |
|
|
53
|
+
| parcourir un service page par page et réagir à une révision | Avis des joueurs, Journal de sessions |
|
|
54
|
+
| maintenir une longue liste défilante sur sa fin, envoyer un message | Chat Twitch |
|
|
55
|
+
| appeler une API HTTP, la mettre en cache dans le stockage, copier dans le presse-papiers | Marché Warframe |
|
|
56
|
+
|
|
57
|
+
Marché Warframe n’est pas un widget intégré : widget PlayerVox du catalogue,
|
|
58
|
+
installé à la demande, il montre des routes réseau avec une limite de
|
|
59
|
+
réponse déclarée, le stockage pour un catalogue en cache et une copie dans
|
|
60
|
+
le presse-papiers sur un clic.
|
|
61
|
+
|
|
62
|
+
## Travailler sur l’un d’eux
|
|
63
|
+
|
|
64
|
+
Depuis une copie de travail du dépôt, liez aux widgets le SDK de cette
|
|
65
|
+
révision, puis vérifiez l’un d’eux, empaquetez-le et lancez ses tests
|
|
66
|
+
unitaires :
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
node scripts/prepare-widgets.mjs
|
|
70
|
+
overcrow-widget check widgets/clock
|
|
71
|
+
overcrow-widget package widgets/clock
|
|
72
|
+
node --test widgets/clock/tests/logic.test.mjs
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`prepare-widgets.mjs` demande que le SDK soit construit d’abord (`npm ci`
|
|
76
|
+
puis `npm run build` dans `sdk/`). Les quatre templates
|
|
77
|
+
d’`overcrow-widget init` se trouvent dans
|
|
78
|
+
[`templates/`](../../../templates/), et deux exemples complets, écrits pour
|
|
79
|
+
ces pages, dans [`docs/content/examples/`](../examples/) : `weather` appelle
|
|
80
|
+
une API HTTP et `countdown` utilise un minuteur, un canvas, un menu
|
|
81
|
+
contextuel et le stockage.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Valhallab SASU
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Clock
|
|
2
|
+
|
|
3
|
+
`com.playervox.overcrow.clock` — the local time of day and, optionally, the
|
|
4
|
+
date on a second line. A built-in of OverCrow, written against the public
|
|
5
|
+
`@overcrow/sdk` and packaged with `overcrow-widget` like any creator's
|
|
6
|
+
widget. MIT.
|
|
7
|
+
|
|
8
|
+
## What it shows
|
|
9
|
+
|
|
10
|
+
| State | Shows |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| Default | `14:08` over `17/07/2026` |
|
|
13
|
+
| Seconds on | `14:08:42` |
|
|
14
|
+
| Date off | the time alone |
|
|
15
|
+
| Date format | `dd/mm/yyyy` (default), `yyyy-mm-dd` or `mm/dd/yyyy`, whatever the user's regional date order |
|
|
16
|
+
|
|
17
|
+
Always 24-hour and zero padded, in English and French alike. The time is
|
|
18
|
+
local: the VM's clock is UTC, and the SDK applies the host's UTC offset
|
|
19
|
+
(`host.region`), which the host sends again at each summer time change.
|
|
20
|
+
|
|
21
|
+
## Menu
|
|
22
|
+
|
|
23
|
+
| Row | Type | Default |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| Show seconds / Afficher les secondes | toggle `show-seconds` | off |
|
|
26
|
+
| Show date / Afficher la date | toggle `show-date` | on |
|
|
27
|
+
| Date format / Format de date | choice `date-format`, shown while the date is | `day-month-year` |
|
|
28
|
+
|
|
29
|
+
## Permissions
|
|
30
|
+
|
|
31
|
+
None. The widget reads no service.
|
|
32
|
+
|
|
33
|
+
## How it works
|
|
34
|
+
|
|
35
|
+
- `timers.atEach("minute" | "second", tick)`: one repeating host timer
|
|
36
|
+
aligned on the local boundary, one VM turn per tick; a tick that drifted
|
|
37
|
+
re-aligns it. No tick while hidden; the time is current at once when the
|
|
38
|
+
widget is shown again.
|
|
39
|
+
- `onHost`: a menu change re-arms the timer at the new unit at once, and a
|
|
40
|
+
new UTC offset shows at once.
|
|
41
|
+
- The accessible label is "Local time {time}, {date}" /
|
|
42
|
+
"Heure locale {time}, {date}".
|
|
43
|
+
|
|
44
|
+
## Tests
|
|
45
|
+
|
|
46
|
+
- `tests/logic.test.mjs`: the logic on `@overcrow/sdk/testing` (formats,
|
|
47
|
+
defaults, the timer and its re-arming).
|
|
48
|
+
- Scenarios, played by `overcrow-widget test` in OverCrow's headless
|
|
49
|
+
runtime, with their reference images: `render` (both themes and
|
|
50
|
+
languages at 100 and 150 %), `options` (each menu row), `ticks` (minutes,
|
|
51
|
+
seconds, midnight), `hidden`, `summer-time` (both changes).
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
node ../../scripts/prepare-widgets.mjs
|
|
55
|
+
overcrow-widget check && overcrow-widget package
|
|
56
|
+
node --test tests/*.test.mjs
|
|
57
|
+
overcrow-widget test --runtime <overcrow-widget-headless>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Cost
|
|
61
|
+
|
|
62
|
+
Measured on 2026-09-30 with OverCrow's release build, on an AMD Ryzen 7
|
|
63
|
+
5800X3D Linux workstation and in a Windows 11 virtual machine (2 vCPU):
|
|
64
|
+
|
|
65
|
+
| | Linux | Windows (VM) |
|
|
66
|
+
| --- | --- | --- |
|
|
67
|
+
| VM start (spawn → ready) | 1.9 ms | 13.5–14.5 ms, sandboxed |
|
|
68
|
+
| Widget start, warm, into the overlay's runtime | 7 ms at most | — |
|
|
69
|
+
| VM memory | 0.55 MiB anonymous | 0.83 MiB private working set |
|
|
70
|
+
| VM CPU per tick, seconds shown | about 95 µs, one VM turn | — |
|
|
71
|
+
| Overlay frames | one each minute (each second with seconds) | — |
|
|
72
|
+
|
|
73
|
+
With the Session and FPS widgets beside it, the overlay's process grows by
|
|
74
|
+
about 2 MB per widget and stays at 0.1 % of one core; nothing runs while
|
|
75
|
+
the overlay is hidden.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"author": "PlayerVox",
|
|
3
|
+
"spdxLicense": "MIT",
|
|
4
|
+
"sourceUrl": "https://github.com/Valhallab/playervox-overcrow-releases/tree/main/widgets/clock",
|
|
5
|
+
"preview": "assets/preview.png",
|
|
6
|
+
"defaultLocale": "en",
|
|
7
|
+
"localizations": [
|
|
8
|
+
{
|
|
9
|
+
"locale": "en",
|
|
10
|
+
"name": "Clock",
|
|
11
|
+
"description": "Shows the local time of day and, optionally, the date, in a 24-hour format."
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"locale": "fr",
|
|
15
|
+
"name": "Horloge",
|
|
16
|
+
"description": "Affiche l’heure locale et, en option, la date, au format 24 heures."
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Clock: the local time of day, 24-hour, and the date in the order the user
|
|
2
|
+
// chose in the widget menu. The VM's clock is UTC: the SDK formats from the
|
|
3
|
+
// host's UTC offset, and its timer wakes at each minute (or second) of local
|
|
4
|
+
// time.
|
|
5
|
+
import {
|
|
6
|
+
formatDate,
|
|
7
|
+
formatTime,
|
|
8
|
+
initState,
|
|
9
|
+
onHost,
|
|
10
|
+
option,
|
|
11
|
+
t,
|
|
12
|
+
timers,
|
|
13
|
+
type DateOrder,
|
|
14
|
+
type Timer,
|
|
15
|
+
} from "@overcrow/sdk";
|
|
16
|
+
|
|
17
|
+
/** The `date-format` menu values and the date order each one means. */
|
|
18
|
+
export const DATE_ORDERS: Readonly<Record<string, DateOrder>> = {
|
|
19
|
+
"day-month-year": "dmy",
|
|
20
|
+
"year-month-day": "ymd",
|
|
21
|
+
"month-day-year": "mdy",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
declare module "@overcrow/sdk" {
|
|
25
|
+
interface WidgetState {
|
|
26
|
+
now: number;
|
|
27
|
+
seconds: boolean;
|
|
28
|
+
showDate: boolean;
|
|
29
|
+
order: DateOrder;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** The menu values, with their defaults. */
|
|
34
|
+
export function menuValues(): { seconds: boolean; showDate: boolean; order: DateOrder } {
|
|
35
|
+
return {
|
|
36
|
+
seconds: option("show-seconds", false),
|
|
37
|
+
showDate: option("show-date", true),
|
|
38
|
+
order: DATE_ORDERS[option("date-format", "day-month-year")] ?? "dmy",
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const state = initState({ now: Date.now(), ...menuValues() });
|
|
43
|
+
|
|
44
|
+
export function clockTime(now: number, seconds: boolean): string {
|
|
45
|
+
return formatTime(now, { seconds });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function clockDate(now: number, order: DateOrder): string {
|
|
49
|
+
return formatDate(now, { order });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function clockLabel(now: number, seconds: boolean, showDate: boolean, order: DateOrder): string {
|
|
53
|
+
const time = clockTime(now, seconds);
|
|
54
|
+
return showDate ? t("label-date", { time, date: clockDate(now, order) }) : t("label", { time });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let clock: Timer | undefined;
|
|
58
|
+
|
|
59
|
+
function tick(): void {
|
|
60
|
+
state.now = Date.now();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Ticks at each second or minute of local time, and shows the time now. */
|
|
64
|
+
function start(): void {
|
|
65
|
+
clock?.cancel();
|
|
66
|
+
clock = timers.atEach(state.seconds ? "second" : "minute", tick);
|
|
67
|
+
tick();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
onHost((changed) => {
|
|
71
|
+
if (changed.includes("options")) {
|
|
72
|
+
const values = menuValues();
|
|
73
|
+
const unitChanged = values.seconds !== state.seconds;
|
|
74
|
+
Object.assign(state, values);
|
|
75
|
+
if (unitChanged) {
|
|
76
|
+
start();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// A new UTC offset (time zone or summer time) shows at once.
|
|
80
|
+
if (changed.includes("region")) {
|
|
81
|
+
tick();
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
start();
|