@monimesl/dot-cli 0.1.0-alpha.2 → 0.1.0-alpha.21

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.
Files changed (116) hide show
  1. package/README.md +91 -17
  2. package/dist/cli.js +832 -156
  3. package/dist/cli.js.map +1 -1
  4. package/dist/server-B9-F93mS.js +11295 -0
  5. package/dist/server-B9-F93mS.js.map +1 -0
  6. package/dist/templates/showcase/.env +3 -0
  7. package/dist/templates/showcase/dot.ts +52 -0
  8. package/dist/templates/showcase/pages/basics/bars/controller.ts +36 -0
  9. package/dist/templates/showcase/pages/basics/bars/state.ts +6 -0
  10. package/dist/templates/showcase/pages/basics/bars/view.dml +28 -0
  11. package/dist/templates/showcase/pages/basics/bindings/controller.ts +15 -0
  12. package/dist/templates/showcase/pages/basics/bindings/state.ts +14 -0
  13. package/dist/templates/showcase/pages/basics/bindings/view.dml +41 -0
  14. package/dist/templates/showcase/pages/basics/control-flow/controller.ts +18 -0
  15. package/dist/templates/showcase/pages/basics/control-flow/state.ts +16 -0
  16. package/dist/templates/showcase/pages/basics/control-flow/view.dml +55 -0
  17. package/dist/templates/showcase/pages/basics/events/controller.ts +43 -0
  18. package/dist/templates/showcase/pages/basics/events/state.ts +11 -0
  19. package/dist/templates/showcase/pages/basics/events/view.dml +51 -0
  20. package/dist/templates/showcase/pages/basics/hooks/controller.ts +43 -0
  21. package/dist/templates/showcase/pages/basics/hooks/state.ts +10 -0
  22. package/dist/templates/showcase/pages/basics/hooks/view.dml +37 -0
  23. package/dist/templates/showcase/pages/basics/navigation/controller.ts +41 -0
  24. package/dist/templates/showcase/pages/basics/navigation/state.ts +11 -0
  25. package/dist/templates/showcase/pages/basics/navigation/view.dml +48 -0
  26. package/dist/templates/showcase/pages/basics/pick-genre/controller.ts +12 -0
  27. package/dist/templates/showcase/pages/basics/pick-genre/state.ts +3 -0
  28. package/dist/templates/showcase/pages/basics/pick-genre/view.dml +9 -0
  29. package/dist/templates/showcase/pages/basics/state/controller.ts +23 -0
  30. package/dist/templates/showcase/pages/basics/state/state.ts +10 -0
  31. package/dist/templates/showcase/pages/basics/state/view.dml +46 -0
  32. package/dist/templates/showcase/pages/components/carousel/controller.ts +41 -0
  33. package/dist/templates/showcase/pages/components/carousel/state.ts +77 -0
  34. package/dist/templates/showcase/pages/components/carousel/view.dml +42 -0
  35. package/dist/templates/showcase/pages/components/feedback/controller.ts +32 -0
  36. package/dist/templates/showcase/pages/components/feedback/state.ts +41 -0
  37. package/dist/templates/showcase/pages/components/feedback/view.dml +116 -0
  38. package/dist/templates/showcase/pages/components/forms/controller.ts +72 -0
  39. package/dist/templates/showcase/pages/components/forms/state.ts +37 -0
  40. package/dist/templates/showcase/pages/components/forms/view.dml +97 -0
  41. package/dist/templates/showcase/pages/components/icons/controller.ts +15 -0
  42. package/dist/templates/showcase/pages/components/icons/state.ts +75 -0
  43. package/dist/templates/showcase/pages/components/icons/view.dml +36 -0
  44. package/dist/templates/showcase/pages/components/images/controller.ts +44 -0
  45. package/dist/templates/showcase/pages/components/images/state.ts +10 -0
  46. package/dist/templates/showcase/pages/components/images/view.dml +83 -0
  47. package/dist/templates/showcase/pages/components/layout/controller.ts +61 -0
  48. package/dist/templates/showcase/pages/components/layout/state.ts +34 -0
  49. package/dist/templates/showcase/pages/components/layout/view.dml +143 -0
  50. package/dist/templates/showcase/pages/components/lists/controller.ts +18 -0
  51. package/dist/templates/showcase/pages/components/lists/state.ts +130 -0
  52. package/dist/templates/showcase/pages/components/lists/view.dml +88 -0
  53. package/dist/templates/showcase/pages/components/money/controller.ts +45 -0
  54. package/dist/templates/showcase/pages/components/money/state.ts +13 -0
  55. package/dist/templates/showcase/pages/components/money/view.dml +54 -0
  56. package/dist/templates/showcase/pages/components/reading/controller.ts +6 -0
  57. package/dist/templates/showcase/pages/components/reading/state.ts +23 -0
  58. package/dist/templates/showcase/pages/components/reading/view.dml +42 -0
  59. package/dist/templates/showcase/pages/components/sheets/controller.ts +36 -0
  60. package/dist/templates/showcase/pages/components/sheets/state.ts +26 -0
  61. package/dist/templates/showcase/pages/components/sheets/view.dml +38 -0
  62. package/dist/templates/showcase/pages/components/styles/controller.ts +6 -0
  63. package/dist/templates/showcase/pages/components/styles/state.ts +3 -0
  64. package/dist/templates/showcase/pages/components/styles/view.dml +101 -0
  65. package/dist/templates/showcase/pages/components/tabs/controller.ts +41 -0
  66. package/dist/templates/showcase/pages/components/tabs/state.ts +127 -0
  67. package/dist/templates/showcase/pages/components/tabs/view.dml +57 -0
  68. package/dist/templates/showcase/pages/components/text/controller.ts +10 -0
  69. package/dist/templates/showcase/pages/components/text/state.ts +3 -0
  70. package/dist/templates/showcase/pages/components/text/view.dml +95 -0
  71. package/dist/templates/showcase/pages/dash/cache/controller.ts +50 -0
  72. package/dist/templates/showcase/pages/dash/cache/state.ts +17 -0
  73. package/dist/templates/showcase/pages/dash/cache/view.dml +48 -0
  74. package/dist/templates/showcase/pages/dash/calls/controller.ts +50 -0
  75. package/dist/templates/showcase/pages/dash/calls/state.ts +6 -0
  76. package/dist/templates/showcase/pages/dash/calls/view.dml +52 -0
  77. package/dist/templates/showcase/pages/dash/contacts/controller.ts +30 -0
  78. package/dist/templates/showcase/pages/dash/contacts/state.ts +6 -0
  79. package/dist/templates/showcase/pages/dash/contacts/view.dml +33 -0
  80. package/dist/templates/showcase/pages/dash/files/controller.ts +91 -0
  81. package/dist/templates/showcase/pages/dash/files/state.ts +24 -0
  82. package/dist/templates/showcase/pages/dash/files/view.dml +79 -0
  83. package/dist/templates/showcase/pages/dash/media/controller.ts +36 -0
  84. package/dist/templates/showcase/pages/dash/media/state.ts +8 -0
  85. package/dist/templates/showcase/pages/dash/media/view.dml +34 -0
  86. package/dist/templates/showcase/pages/dash/network/controller.ts +215 -0
  87. package/dist/templates/showcase/pages/dash/network/state.ts +35 -0
  88. package/dist/templates/showcase/pages/dash/network/view.dml +108 -0
  89. package/dist/templates/showcase/pages/dash/secrets/controller.ts +44 -0
  90. package/dist/templates/showcase/pages/dash/secrets/state.ts +5 -0
  91. package/dist/templates/showcase/pages/dash/secrets/view.dml +26 -0
  92. package/dist/templates/showcase/pages/dash/system/controller.ts +89 -0
  93. package/dist/templates/showcase/pages/dash/system/state.ts +13 -0
  94. package/dist/templates/showcase/pages/dash/system/view.dml +97 -0
  95. package/dist/templates/showcase/pages/dash/ui/controller.ts +70 -0
  96. package/dist/templates/showcase/pages/dash/ui/state.ts +8 -0
  97. package/dist/templates/showcase/pages/dash/ui/view.dml +31 -0
  98. package/dist/templates/showcase/pages/index/controller.ts +10 -0
  99. package/dist/templates/showcase/pages/index/state.ts +212 -0
  100. package/dist/templates/showcase/pages/index/view.dml +23 -0
  101. package/dist/templates/showcase/statics/logo.png +0 -0
  102. package/dist/templates/starter/.env +3 -0
  103. package/dist/templates/starter/dot.ts +3 -0
  104. package/dist/templates/starter/pages/index/controller.ts +9 -0
  105. package/dist/templates/starter/pages/index/state.ts +4 -0
  106. package/dist/templates/starter/pages/index/view.dml +16 -0
  107. package/package.json +12 -7
  108. package/dist/template/.env +0 -3
  109. package/dist/template/dot.ts +0 -6
  110. package/dist/template/pages/help/tips/controller.ts +0 -30
  111. package/dist/template/pages/help/tips/state.ts +0 -11
  112. package/dist/template/pages/help/tips/view.dml +0 -15
  113. package/dist/template/pages/index/controller.ts +0 -67
  114. package/dist/template/pages/index/state.ts +0 -17
  115. package/dist/template/pages/index/view.dml +0 -66
  116. /package/dist/{template → templates/starter}/statics/logo.png +0 -0
@@ -0,0 +1,44 @@
1
+ import state from './state';
2
+
3
+ const SESSION = 'session';
4
+ const NAME = 'session-name';
5
+
6
+ export default definePage({
7
+ initialState: state,
8
+ configs: { navigationBar: { title: 'dash.storage.secret' } },
9
+ hooks: {
10
+ async onShow() {
11
+ await this.actions.refresh();
12
+ },
13
+ },
14
+ mutations: {
15
+ setName: (_state, event: ValueEvent) => ({ name: event.detail.value }),
16
+ },
17
+ actions: {
18
+ async refresh() {
19
+ const token = await this.dash.storage.secret.get(SESSION);
20
+ const signedInAs = await this.dash.storage.cache.get<string>(NAME);
21
+ this.setState({
22
+ token: token ? `${token.slice(0, 12)}…` : '',
23
+ signedInAs: signedInAs ?? '',
24
+ });
25
+ },
26
+ async signIn(state) {
27
+ // A real dot gets its token from its own API, once the person signs in there.
28
+ const token = `demo-${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;
29
+ await this.dash.storage.secret.set(SESSION, token);
30
+ await this.dash.storage.cache.set(NAME, state.name);
31
+ this.setState({ name: '' });
32
+ await this.actions.refresh();
33
+ },
34
+ async signOut() {
35
+ await this.dash.storage.secret.remove(SESSION);
36
+ await this.dash.storage.cache.remove(NAME);
37
+ await this.actions.refresh();
38
+ },
39
+ async forgetAll() {
40
+ await this.dash.storage.secret.clear();
41
+ await this.actions.refresh();
42
+ },
43
+ },
44
+ });
@@ -0,0 +1,5 @@
1
+ export default {
2
+ name: '',
3
+ signedInAs: '',
4
+ token: '',
5
+ };
@@ -0,0 +1,26 @@
1
+ <View>
2
+ <Text variant="title">dash.storage.secret</Text>
3
+ <Text>Secrets hold sign-in tokens from the dot's own server. Dash keeps them encrypted on the phone. A dot can keep up to 8, of up to 4 KB each.</Text>
4
+
5
+ <View gap="small">
6
+ <Text variant="subtitle">set, get, remove and clear</Text>
7
+ <Text variant="caption" tone="muted">A sign-in that stays. Sign out removes the token, and Forget every secret clears them all.</Text>
8
+ <View variant="card" gap="small">
9
+ <If condition="{{ token }}">
10
+ <Text>Signed in as {{ signedInAs }}</Text>
11
+ <Text variant="caption" tone="muted">Session token {{ token }}</Text>
12
+ <View direction="row" gap="small">
13
+ <Button variant="secondary" onClick="signOut">Sign out</Button>
14
+ <Button variant="secondary" onClick="forgetAll">Forget every secret</Button>
15
+ </View>
16
+ </If>
17
+ <Else>
18
+ <Input label="Name" placeholder="Mariama" value="{{ name }}" maxLength="40" onChange="setName" onSubmit="signIn" />
19
+ <Button onClick="signIn" disabled="{{ !name }}">Sign in</Button>
20
+ <Text variant="caption" tone="muted">Sign in, then close and reopen the dot. You stay signed in.</Text>
21
+ </Else>
22
+ </View>
23
+ </View>
24
+
25
+ <Notice tone="warning" title="Keep keys off the phone">Only the token is a secret here: your name is in the cache. Never put API keys in a dot's code or .env, since anyone with the dot can read them.</Notice>
26
+ </View>
@@ -0,0 +1,89 @@
1
+ import type { VibrationStyle } from '@monimesl/dot-runtime';
2
+ import { errorMessage } from '@monimesl/dot-runtime';
3
+
4
+ import state from './state';
5
+
6
+ export default definePage({
7
+ initialState: state,
8
+ configs: { navigationBar: { title: 'dash.system' } },
9
+ mutations: {
10
+ clearToast: () => ({ toast: '' }),
11
+ setNumber: (_state, event: ValueEvent) => ({ number: event.detail.value }),
12
+ },
13
+ actions: {
14
+ async vibrate(_state, event: DataEvent<{ style: VibrationStyle }>) {
15
+ await this.dash.system.vibrate({ style: event.data.style });
16
+ },
17
+ async copySong() {
18
+ await this.dash.system.copyText('Exodus, by Drizilik');
19
+ this.setState({ toast: 'Song copied' });
20
+ },
21
+ async shareText() {
22
+ try {
23
+ await this.dash.system.share({
24
+ text: 'Salone Sounds Live, Freetown, 24 October. See you there!',
25
+ });
26
+ } catch (error) {
27
+ this.setState({ note: errorMessage(error) });
28
+ }
29
+ },
30
+ async shareLink() {
31
+ try {
32
+ await this.dash.system.share({
33
+ title: 'Music of Sierra Leone',
34
+ url: 'https://en.wikipedia.org/wiki/Music_of_Sierra_Leone',
35
+ });
36
+ } catch (error) {
37
+ this.setState({ note: errorMessage(error) });
38
+ }
39
+ },
40
+ async openDrizilik() {
41
+ try {
42
+ await this.dash.system.openUrl('https://drizilik.com/');
43
+ } catch (error) {
44
+ this.setState({ note: errorMessage(error) });
45
+ }
46
+ },
47
+ async countDown() {
48
+ for (let seconds = 10; seconds > 0; seconds--) {
49
+ this.setState({ showIn: seconds });
50
+ await this.dash.system.delay(1000);
51
+ }
52
+ this.setState({ showIn: 0, toast: "It's showtime" });
53
+ },
54
+ async readInfo() {
55
+ try {
56
+ this.setState({ info: await this.dash.system.info(), note: '' });
57
+ } catch (error) {
58
+ this.setState({ note: errorMessage(error) });
59
+ }
60
+ },
61
+ async toggleTicket(state) {
62
+ const ticketShown = !state.ticketShown;
63
+ try {
64
+ await this.dash.system.keepAwake(ticketShown);
65
+ await this.dash.system.brightness(ticketShown ? 'max' : 'normal');
66
+ this.setState({ ticketShown, note: '' });
67
+ } catch (error) {
68
+ this.setState({ note: errorMessage(error) });
69
+ }
70
+ },
71
+ async dialNumber(state) {
72
+ try {
73
+ await this.dash.system.dial(state.number);
74
+ this.setState({ note: '' });
75
+ } catch (error) {
76
+ this.setState({ note: errorMessage(error) });
77
+ }
78
+ },
79
+ async toggleTorch(state) {
80
+ const next = state.torch === 'on' ? 'off' : 'on';
81
+ try {
82
+ await this.dash.system.torch(next);
83
+ this.setState({ torch: next, note: '' });
84
+ } catch (error) {
85
+ this.setState({ note: errorMessage(error) });
86
+ }
87
+ },
88
+ },
89
+ });
@@ -0,0 +1,13 @@
1
+ import type { SystemInfo, TorchState, VibrationStyle } from '@monimesl/dot-runtime';
2
+
3
+ export default {
4
+ styles: ['light', 'medium', 'heavy', 'success', 'warning', 'error'] as VibrationStyle[],
5
+ torch: 'off' as TorchState,
6
+ info: null as SystemInfo | null,
7
+ // The ticket's QR code shows awake and bright, so a scanner at the door reads it.
8
+ ticketShown: false,
9
+ number: '*715#',
10
+ showIn: 0,
11
+ note: '',
12
+ toast: '',
13
+ };
@@ -0,0 +1,97 @@
1
+ <View>
2
+ <Text variant="title">dash.system</Text>
3
+ <Text>The phone's own features: what it is, its screen, vibration, the clipboard, sharing, the browser, the dialer, timers and the torch.</Text>
4
+
5
+ <View gap="small">
6
+ <Text variant="subtitle">info</Text>
7
+ <Text variant="caption" tone="muted">The phone and the app the dot runs in, without anything that identifies the person or the phone.</Text>
8
+ <View variant="card" gap="none">
9
+ <If condition="{{ info }}">
10
+ <DetailRow label="Platform" value="{{ info.platform }} {{ info.osVersion }}" />
11
+ <DetailRow label="Language" value="{{ info.language }}{{ info.region ? ' · ' + info.region : '' }}" />
12
+ <DetailRow label="Time zone" value="{{ info.timeZone }}" />
13
+ <DetailRow label="Dash" value="{{ info.dashVersion }}" />
14
+ <DetailRow label="DotHost" value="{{ info.hostVersion }}" />
15
+ </If>
16
+ <Else>
17
+ <Button variant="secondary" onClick="readInfo">Read the phone's details</Button>
18
+ </Else>
19
+ </View>
20
+ </View>
21
+
22
+ <View gap="small">
23
+ <Text variant="subtitle">keepAwake and brightness</Text>
24
+ <Text variant="caption" tone="muted">Keep the screen on and as bright as it goes while a QR code shows, so a scanner reads it. Dash puts both back when the dot closes.</Text>
25
+ <View variant="card" align="center" gap="medium">
26
+ <If condition="{{ ticketShown }}">
27
+ <QRCode value="TICKET-SSL-0042" size="160" label="Your ticket's QR code" />
28
+ <Text tone="muted">Show this at the door</Text>
29
+ </If>
30
+ <Button variant="secondary" onClick="toggleTicket">{{ ticketShown ? 'Hide the ticket' : 'Show my ticket' }}</Button>
31
+ </View>
32
+ </View>
33
+
34
+ <View gap="small">
35
+ <Text variant="subtitle">vibrate</Text>
36
+ <Text variant="caption" tone="muted">A short buzz, in a style that suits what happened.</Text>
37
+ <View variant="card" direction="row" wrap gap="small">
38
+ <For each="{{ styles }}" item="style" key="*this">
39
+ <Button variant="secondary" data-style="{{ style }}" onClick="vibrate">{{ style }}</Button>
40
+ </For>
41
+ </View>
42
+ </View>
43
+
44
+ <View gap="small">
45
+ <Text variant="subtitle">copyText</Text>
46
+ <View variant="card">
47
+ <Button variant="secondary" onClick="copySong">Copy a song's name</Button>
48
+ </View>
49
+ </View>
50
+
51
+ <View gap="small">
52
+ <Text variant="subtitle">share</Text>
53
+ <Text variant="caption" tone="muted">Opens the phone's share sheet with text, a link or a file. The dash.network page shares a file.</Text>
54
+ <View variant="card" direction="row" wrap gap="small">
55
+ <Button variant="secondary" onClick="shareText">Share text</Button>
56
+ <Button variant="secondary" onClick="shareLink">Share a link</Button>
57
+ </View>
58
+ </View>
59
+
60
+ <View gap="small">
61
+ <Text variant="subtitle">openUrl</Text>
62
+ <Text variant="caption" tone="muted">Opens a web page in the phone's browser.</Text>
63
+ <View variant="card">
64
+ <Button variant="secondary" onClick="openDrizilik">Open Drizilik's website</Button>
65
+ </View>
66
+ </View>
67
+
68
+ <View gap="small">
69
+ <Text variant="subtitle">delay</Text>
70
+ <Text variant="caption" tone="muted">Waits for a number of milliseconds. Dash keeps time, so it's cancelled when the page closes.</Text>
71
+ <View variant="card">
72
+ <Button variant="secondary" onClick="countDown" disabled="{{ showIn > 0 }}">{{ showIn > 0 ? 'Showtime in ' + showIn + 's' : 'Count down to showtime' }}</Button>
73
+ </View>
74
+ </View>
75
+
76
+ <View gap="small">
77
+ <Text variant="subtitle">dial</Text>
78
+ <Text variant="caption" tone="muted">Opens the phone's dialer with a number ready, or a USSD code such as *715#. The person taps Call.</Text>
79
+ <View variant="card">
80
+ <Input label="Number or code" type="phone" value="{{ number }}" onChange="setNumber" onSubmit="dialNumber" />
81
+ <Button variant="secondary" onClick="dialNumber" disabled="{{ !number }}">Open the dialer</Button>
82
+ </View>
83
+ </View>
84
+
85
+ <View gap="small">
86
+ <Text variant="subtitle">torch</Text>
87
+ <Text variant="caption" tone="muted">Turns the camera's light on or off.</Text>
88
+ <View variant="card">
89
+ <Button variant="secondary" onClick="toggleTorch">{{ torch === 'on' ? 'Turn the torch off' : 'Lights up for the slow song' }}</Button>
90
+ </View>
91
+ </View>
92
+
93
+ <If condition="{{ note }}">
94
+ <Notice tone="danger">{{ note }}</Notice>
95
+ </If>
96
+ <Toast message="{{ toast }}" tone="success" onHide="clearToast" />
97
+ </View>
@@ -0,0 +1,70 @@
1
+ import { errorMessage, unlessCancelled } from '@monimesl/dot-runtime';
2
+
3
+ import state from './state';
4
+
5
+ export default definePage({
6
+ initialState: state,
7
+ configs: { navigationBar: { title: 'dash.ui' } },
8
+ actions: {
9
+ async greet() {
10
+ try {
11
+ const { action } = await this.dash.ui.alert({
12
+ title: 'Kushé',
13
+ message: 'Kushé means hello in Krio, and tenki means thanks.',
14
+ actions: [
15
+ { id: 'tenki', label: 'Tenki' },
16
+ { id: 'close', label: 'Close', role: 'cancel' },
17
+ ],
18
+ });
19
+ this.setState({ choice: action, note: '' });
20
+ } catch (error) {
21
+ this.setState({ note: errorMessage(error) });
22
+ }
23
+ },
24
+ async confirmRemove() {
25
+ try {
26
+ const { action } = await this.dash.ui.alert({
27
+ title: 'Remove this song from your library?',
28
+ message: 'Its download goes too.',
29
+ actions: [
30
+ { id: 'keep', label: 'Keep', role: 'cancel' },
31
+ { id: 'remove', label: 'Remove', role: 'destructive' },
32
+ ],
33
+ });
34
+ this.setState({ choice: action, note: '' });
35
+ } catch (error) {
36
+ this.setState({ note: errorMessage(error) });
37
+ }
38
+ },
39
+ // unlessCancelled gives undefined when the person closes the picker, which isn't a problem.
40
+ async chooseNight(state) {
41
+ try {
42
+ const night = await unlessCancelled(
43
+ this.dash.ui.pickDate({
44
+ title: 'Choose a night',
45
+ value: state.night || undefined,
46
+ min: '2026-10-01',
47
+ max: '2026-12-31',
48
+ }),
49
+ );
50
+ if (night) {
51
+ this.setState({ night, note: '' });
52
+ }
53
+ } catch (error) {
54
+ this.setState({ note: errorMessage(error) });
55
+ }
56
+ },
57
+ async chooseArrival(state) {
58
+ try {
59
+ const arrival = await unlessCancelled(
60
+ this.dash.ui.pickTime({ title: 'Arriving at', value: state.arrival || '18:00' }),
61
+ );
62
+ if (arrival) {
63
+ this.setState({ arrival, note: '' });
64
+ }
65
+ } catch (error) {
66
+ this.setState({ note: errorMessage(error) });
67
+ }
68
+ },
69
+ },
70
+ });
@@ -0,0 +1,8 @@
1
+ export default {
2
+ // The id of the alert button tapped.
3
+ choice: '',
4
+ // A date such as "2026-10-24", and a time such as "19:30", from the phone's own pickers.
5
+ night: '',
6
+ arrival: '',
7
+ note: '',
8
+ };
@@ -0,0 +1,31 @@
1
+ <View>
2
+ <Text variant="title">dash.ui</Text>
3
+ <Text>Dash shows these over the dot, in the phone's own style. Each call waits until the person answers.</Text>
4
+
5
+ <View gap="small">
6
+ <Text variant="subtitle">alert</Text>
7
+ <Text variant="caption" tone="muted">A title, a message and buttons. It gives back the id of the button tapped. role="cancel" and role="destructive" style a button.</Text>
8
+ <View variant="card" gap="small">
9
+ <View direction="row" wrap gap="small">
10
+ <Button onClick="greet">Say kushé</Button>
11
+ <Button variant="secondary" onClick="confirmRemove">Remove a song</Button>
12
+ </View>
13
+ <If condition="{{ choice }}">
14
+ <Text>You tapped "{{ choice }}"</Text>
15
+ </If>
16
+ </View>
17
+ </View>
18
+
19
+ <View gap="small">
20
+ <Text variant="subtitle">pickDate and pickTime</Text>
21
+ <Text variant="caption" tone="muted">The phone's own pickers. A date comes back as "2026-10-24" and a time as "19:30". min and max limit the dates. Closing a picker rejects with a DashError coded cancelled.</Text>
22
+ <List>
23
+ <ListItem icon="calendar" title="Night" subtitle="Shows run from October to December" value="{{ night || 'Choose' }}" onTap="chooseNight" />
24
+ <ListItem icon="clock" title="Arriving at" subtitle="Doors open at 18:00" value="{{ arrival || 'Choose' }}" onTap="chooseArrival" />
25
+ </List>
26
+ </View>
27
+
28
+ <If condition="{{ note }}">
29
+ <Notice tone="danger">{{ note }}</Notice>
30
+ </If>
31
+ </View>
@@ -0,0 +1,10 @@
1
+ import state from './state';
2
+
3
+ export default definePage({
4
+ initialState: state,
5
+ actions: {
6
+ open(_state, event: DataEvent<{ page: PageId }>) {
7
+ this.navigation.push(event.data.page);
8
+ },
9
+ },
10
+ });
@@ -0,0 +1,212 @@
1
+ export interface Topic {
2
+ page: PageId;
3
+ title: string;
4
+ // The API names the page shows, so it's easy to find the one you need.
5
+ covers: string;
6
+ icon: string;
7
+ }
8
+
9
+ export interface Section {
10
+ title: string;
11
+ text: string;
12
+ topics: Topic[];
13
+ }
14
+
15
+ export default {
16
+ title: 'Salone Sounds',
17
+ sections: [
18
+ {
19
+ title: 'Basics',
20
+ text: 'How a page works: pages/<name>/ with state.ts, view.dml and controller.ts',
21
+ topics: [
22
+ {
23
+ page: 'basics/state',
24
+ title: 'State, mutations and actions',
25
+ covers: 'state.ts, setState, mutations, actions',
26
+ icon: 'refresh',
27
+ },
28
+ {
29
+ page: 'basics/bindings',
30
+ title: 'Bindings',
31
+ covers: '{{ }}, expressions, env',
32
+ icon: 'link',
33
+ },
34
+ {
35
+ page: 'basics/control-flow',
36
+ title: 'If and For',
37
+ covers: 'If, ElseIf, Else, For',
38
+ icon: 'list',
39
+ },
40
+ {
41
+ page: 'basics/events',
42
+ title: 'Events',
43
+ covers: 'onTap, onChange, event.detail, data-*',
44
+ icon: 'bolt',
45
+ },
46
+ {
47
+ page: 'basics/navigation',
48
+ title: 'Navigation',
49
+ covers: 'push, replace, back, reset, pushForResult, backWithResult',
50
+ icon: 'arrow-right',
51
+ },
52
+ {
53
+ page: 'basics/hooks',
54
+ title: 'Page hooks',
55
+ covers: 'onLoad, onShow, onHide, onUnload, onRefresh',
56
+ icon: 'history',
57
+ },
58
+ {
59
+ page: 'basics/bars',
60
+ title: "Dash's bars",
61
+ covers: 'configs, setNavigationBar, setTabBar',
62
+ icon: 'settings',
63
+ },
64
+ ],
65
+ },
66
+ {
67
+ title: 'Components',
68
+ text: 'What a view.dml can show',
69
+ topics: [
70
+ {
71
+ page: 'components/layout',
72
+ title: 'Layout',
73
+ covers: 'View, Stack, Scroll, Grid, Divider',
74
+ icon: 'grid',
75
+ },
76
+ {
77
+ page: 'components/styles',
78
+ title: 'Styles',
79
+ covers: 'background, border, radius, sizes, theme colours',
80
+ icon: 'star',
81
+ },
82
+ {
83
+ page: 'components/text',
84
+ title: 'Text and links',
85
+ covers: 'Text, Link',
86
+ icon: 'edit',
87
+ },
88
+ {
89
+ page: 'components/icons',
90
+ title: 'Icons',
91
+ covers: 'Icon, every name',
92
+ icon: 'heart',
93
+ },
94
+ {
95
+ page: 'components/reading',
96
+ title: 'Reading',
97
+ covers: 'Prose, Quote, BulletList, RichText',
98
+ icon: 'file',
99
+ },
100
+ {
101
+ page: 'components/images',
102
+ title: 'Images',
103
+ covers: 'Image, Avatar',
104
+ icon: 'image',
105
+ },
106
+ {
107
+ page: 'components/carousel',
108
+ title: 'Carousel',
109
+ covers: 'Carousel',
110
+ icon: 'video',
111
+ },
112
+ {
113
+ page: 'components/lists',
114
+ title: 'Lists',
115
+ covers: 'List, ListItem, DetailRow, Disclosure, EmptyState',
116
+ icon: 'list',
117
+ },
118
+ {
119
+ page: 'components/tabs',
120
+ title: 'Tabs and chips',
121
+ covers: 'Tabs, Tab, Chip',
122
+ icon: 'search',
123
+ },
124
+ {
125
+ page: 'components/forms',
126
+ title: 'Forms',
127
+ covers: 'Input, TextArea, Select, Stepper, Checkbox, Radio, Switch, Slider, Footer',
128
+ icon: 'check',
129
+ },
130
+ {
131
+ page: 'components/money',
132
+ title: 'Money and codes',
133
+ covers: 'AmountInput, CodeInput, QRCode',
134
+ icon: 'cash',
135
+ },
136
+ {
137
+ page: 'components/feedback',
138
+ title: 'Feedback',
139
+ covers: 'Spinner, Skeleton, ProgressBar, Notice, Steps, Badge, Toast',
140
+ icon: 'bell',
141
+ },
142
+ {
143
+ page: 'components/sheets',
144
+ title: 'Sheets',
145
+ covers: 'Sheet',
146
+ icon: 'more',
147
+ },
148
+ ],
149
+ },
150
+ {
151
+ title: 'Dash',
152
+ text: "The phone's features, through this.dash",
153
+ topics: [
154
+ {
155
+ page: 'dash/ui',
156
+ title: 'dash.ui',
157
+ covers: 'alert, pickDate, pickTime',
158
+ icon: 'calendar',
159
+ },
160
+ {
161
+ page: 'dash/system',
162
+ title: 'dash.system',
163
+ covers:
164
+ 'info, keepAwake, brightness, vibrate, copyText, share, openUrl, dial, delay, torch',
165
+ icon: 'mobile',
166
+ },
167
+ {
168
+ page: 'dash/media',
169
+ title: 'dash.media',
170
+ covers: 'pickPhoto, scanCode',
171
+ icon: 'image',
172
+ },
173
+ {
174
+ page: 'dash/contacts',
175
+ title: 'dash.contacts',
176
+ covers: 'pickPhone',
177
+ icon: 'users',
178
+ },
179
+ {
180
+ page: 'dash/network',
181
+ title: 'dash.network',
182
+ covers: 'status, http.request, http.download, http.upload, debounce, latest',
183
+ icon: 'wifi',
184
+ },
185
+ {
186
+ page: 'dash/files',
187
+ title: 'dash.storage.file',
188
+ covers: 'write, read, list, move, copy, pick, save',
189
+ icon: 'file',
190
+ },
191
+ {
192
+ page: 'dash/cache',
193
+ title: 'dash.storage.cache',
194
+ covers: 'set, get, keys, exists, remove, clear',
195
+ icon: 'history',
196
+ },
197
+ {
198
+ page: 'dash/secrets',
199
+ title: 'dash.storage.secret',
200
+ covers: 'set, get, remove, clear',
201
+ icon: 'lock',
202
+ },
203
+ {
204
+ page: 'dash/calls',
205
+ title: 'Calls and errors',
206
+ covers: 'timeout, cancel, DashError, isDashError, isDashCancelled',
207
+ icon: 'warning',
208
+ },
209
+ ],
210
+ },
211
+ ] as Section[],
212
+ };
@@ -0,0 +1,23 @@
1
+ <View>
2
+ <View direction="row" align="center" gap="large">
3
+ <Image src="statics/logo.png" alt="Salone Sounds logo" width="48" height="48" />
4
+ <View gap="none">
5
+ <Text variant="title">{{ title }}</Text>
6
+ <Text variant="caption" tone="muted">What a dot can do, shown with Sierra Leone's music</Text>
7
+ </View>
8
+ </View>
9
+
10
+ <For each="{{ sections }}" item="section" key="title">
11
+ <View gap="small">
12
+ <View gap="none">
13
+ <Text variant="subtitle">{{ section.title }}</Text>
14
+ <Text variant="caption" tone="muted">{{ section.text }}</Text>
15
+ </View>
16
+ <List>
17
+ <For each="{{ section.topics }}" item="topic" key="page">
18
+ <ListItem icon="{{ topic.icon }}" title="{{ topic.title }}" subtitle="{{ topic.covers }}" data-page="{{ topic.page }}" onTap="open" />
19
+ </For>
20
+ </List>
21
+ </View>
22
+ </For>
23
+ </View>
@@ -0,0 +1,3 @@
1
+ # Public configuration for the dot. Anyone with the dot can read these variables: never put a
2
+ # secret here. Read them in the service as `env.GREETING`.
3
+ GREETING=Hello from your dot
@@ -0,0 +1,3 @@
1
+ export default defineDot({
2
+ pages: ['index'],
3
+ });
@@ -0,0 +1,9 @@
1
+ import state from './state';
2
+
3
+ export default definePage({
4
+ initialState: state,
5
+ mutations: {
6
+ increment: (state) => ({ count: state.count + 1 }),
7
+ reset: () => ({ count: 0 }),
8
+ },
9
+ });
@@ -0,0 +1,4 @@
1
+ export default {
2
+ greeting: env.GREETING,
3
+ count: 0,
4
+ };