@monimesl/dot-cli 0.1.0-alpha.16 → 0.1.0-alpha.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +16 -9
- package/dist/cli.js.map +1 -1
- package/dist/templates/showcase/dot.ts +32 -17
- package/dist/templates/showcase/pages/basics/bars/controller.ts +36 -0
- package/dist/templates/showcase/pages/basics/bars/state.ts +6 -0
- package/dist/templates/showcase/pages/basics/bars/view.dml +28 -0
- package/dist/templates/showcase/pages/{text → basics/bindings}/controller.ts +4 -0
- package/dist/templates/showcase/pages/basics/bindings/state.ts +14 -0
- package/dist/templates/showcase/pages/basics/bindings/view.dml +41 -0
- package/dist/templates/showcase/pages/basics/control-flow/controller.ts +17 -0
- package/dist/templates/showcase/pages/basics/control-flow/state.ts +16 -0
- package/dist/templates/showcase/pages/basics/control-flow/view.dml +55 -0
- package/dist/templates/showcase/pages/basics/events/controller.ts +42 -0
- package/dist/templates/showcase/pages/basics/events/state.ts +11 -0
- package/dist/templates/showcase/pages/basics/events/view.dml +51 -0
- package/dist/templates/showcase/pages/basics/hooks/controller.ts +36 -0
- package/dist/templates/showcase/pages/basics/hooks/state.ts +10 -0
- package/dist/templates/showcase/pages/basics/hooks/view.dml +32 -0
- package/dist/templates/showcase/pages/basics/navigation/controller.ts +33 -0
- package/dist/templates/showcase/pages/basics/navigation/state.ts +9 -0
- package/dist/templates/showcase/pages/basics/navigation/view.dml +37 -0
- package/dist/templates/showcase/pages/basics/state/view.dml +46 -0
- package/dist/templates/showcase/pages/{carousel → components/carousel}/view.dml +7 -5
- package/dist/templates/showcase/pages/{feedback → components/feedback}/view.dml +18 -9
- package/dist/templates/showcase/pages/{forms → components/forms}/controller.ts +4 -1
- package/dist/templates/showcase/pages/{forms → components/forms}/state.ts +3 -0
- package/dist/templates/showcase/pages/components/forms/view.dml +90 -0
- package/dist/templates/showcase/pages/components/icons/controller.ts +14 -0
- package/dist/templates/showcase/pages/components/icons/state.ts +75 -0
- package/dist/templates/showcase/pages/components/icons/view.dml +36 -0
- package/dist/templates/showcase/pages/components/images/view.dml +70 -0
- package/dist/templates/showcase/pages/components/layout/view.dml +143 -0
- package/dist/templates/showcase/pages/components/lists/controller.ts +17 -0
- package/dist/templates/showcase/pages/{lists → components/lists}/state.ts +43 -30
- package/dist/templates/showcase/pages/components/lists/view.dml +70 -0
- package/dist/templates/showcase/pages/{payments → components/money}/view.dml +17 -8
- package/dist/templates/showcase/pages/components/reading/state.ts +23 -0
- package/dist/templates/showcase/pages/components/reading/view.dml +42 -0
- package/dist/templates/showcase/pages/{lists → components/sheets}/controller.ts +8 -10
- package/dist/templates/showcase/pages/components/sheets/state.ts +26 -0
- package/dist/templates/showcase/pages/components/sheets/view.dml +38 -0
- package/dist/templates/showcase/pages/components/styles/controller.ts +5 -0
- package/dist/templates/showcase/pages/components/styles/view.dml +101 -0
- package/dist/templates/showcase/pages/{filters → components/tabs}/controller.ts +1 -0
- package/dist/templates/showcase/pages/{filters → components/tabs}/state.ts +1 -0
- package/dist/templates/showcase/pages/components/tabs/view.dml +56 -0
- package/dist/templates/showcase/pages/components/text/controller.ts +9 -0
- package/dist/templates/showcase/pages/components/text/state.ts +3 -0
- package/dist/templates/showcase/pages/components/text/view.dml +95 -0
- package/dist/templates/showcase/pages/{cache → dash/cache}/controller.ts +4 -0
- package/dist/templates/showcase/pages/dash/cache/view.dml +48 -0
- package/dist/templates/showcase/pages/dash/calls/controller.ts +48 -0
- package/dist/templates/showcase/pages/dash/calls/state.ts +6 -0
- package/dist/templates/showcase/pages/dash/calls/view.dml +51 -0
- package/dist/templates/showcase/pages/dash/files/view.dml +79 -0
- package/dist/templates/showcase/pages/dash/media/controller.ts +32 -0
- package/dist/templates/showcase/pages/{device → dash/media}/state.ts +0 -4
- package/dist/templates/showcase/pages/dash/media/view.dml +34 -0
- package/dist/templates/showcase/pages/dash/network/view.dml +80 -0
- package/dist/templates/showcase/pages/dash/secrets/view.dml +26 -0
- package/dist/templates/showcase/pages/dash/system/controller.ts +61 -0
- package/dist/templates/showcase/pages/dash/system/state.ts +9 -0
- package/dist/templates/showcase/pages/dash/system/view.dml +59 -0
- package/dist/templates/showcase/pages/dash/ui/controller.ts +69 -0
- package/dist/templates/showcase/pages/dash/ui/state.ts +8 -0
- package/dist/templates/showcase/pages/dash/ui/view.dml +31 -0
- package/dist/templates/showcase/pages/index/state.ts +135 -64
- package/dist/templates/showcase/pages/index/view.dml +6 -3
- package/package.json +6 -6
- package/dist/templates/showcase/pages/cache/view.dml +0 -36
- package/dist/templates/showcase/pages/device/controller.ts +0 -105
- package/dist/templates/showcase/pages/device/view.dml +0 -69
- package/dist/templates/showcase/pages/files/view.dml +0 -64
- package/dist/templates/showcase/pages/filters/view.dml +0 -44
- package/dist/templates/showcase/pages/forms/view.dml +0 -49
- package/dist/templates/showcase/pages/images/view.dml +0 -53
- package/dist/templates/showcase/pages/layout/view.dml +0 -103
- package/dist/templates/showcase/pages/lists/view.dml +0 -59
- package/dist/templates/showcase/pages/navigation/controller.ts +0 -65
- package/dist/templates/showcase/pages/navigation/state.ts +0 -17
- package/dist/templates/showcase/pages/navigation/view.dml +0 -34
- package/dist/templates/showcase/pages/network/view.dml +0 -67
- package/dist/templates/showcase/pages/secrets/view.dml +0 -24
- package/dist/templates/showcase/pages/state/view.dml +0 -33
- package/dist/templates/showcase/pages/styles/view.dml +0 -61
- package/dist/templates/showcase/pages/text/state.ts +0 -8
- package/dist/templates/showcase/pages/text/view.dml +0 -58
- /package/dist/templates/showcase/pages/{state → basics/state}/controller.ts +0 -0
- /package/dist/templates/showcase/pages/{state → basics/state}/state.ts +0 -0
- /package/dist/templates/showcase/pages/{carousel → components/carousel}/controller.ts +0 -0
- /package/dist/templates/showcase/pages/{carousel → components/carousel}/state.ts +0 -0
- /package/dist/templates/showcase/pages/{feedback → components/feedback}/controller.ts +0 -0
- /package/dist/templates/showcase/pages/{feedback → components/feedback}/state.ts +0 -0
- /package/dist/templates/showcase/pages/{images → components/images}/controller.ts +0 -0
- /package/dist/templates/showcase/pages/{images → components/images}/state.ts +0 -0
- /package/dist/templates/showcase/pages/{layout → components/layout}/controller.ts +0 -0
- /package/dist/templates/showcase/pages/{layout → components/layout}/state.ts +0 -0
- /package/dist/templates/showcase/pages/{payments → components/money}/controller.ts +0 -0
- /package/dist/templates/showcase/pages/{payments → components/money}/state.ts +0 -0
- /package/dist/templates/showcase/pages/{styles → components/reading}/controller.ts +0 -0
- /package/dist/templates/showcase/pages/{styles → components/styles}/state.ts +0 -0
- /package/dist/templates/showcase/pages/{cache → dash/cache}/state.ts +0 -0
- /package/dist/templates/showcase/pages/{files → dash/files}/controller.ts +0 -0
- /package/dist/templates/showcase/pages/{files → dash/files}/state.ts +0 -0
- /package/dist/templates/showcase/pages/{network → dash/network}/controller.ts +0 -0
- /package/dist/templates/showcase/pages/{network → dash/network}/state.ts +0 -0
- /package/dist/templates/showcase/pages/{secrets → dash/secrets}/controller.ts +0 -0
- /package/dist/templates/showcase/pages/{secrets → dash/secrets}/state.ts +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<View>
|
|
2
|
+
<Text variant="title">Bindings</Text>
|
|
3
|
+
<Text>Write {{ syntax }} in view.dml to show a value from the page's state. The view changes when the state does.</Text>
|
|
4
|
+
|
|
5
|
+
<View gap="small">
|
|
6
|
+
<Text variant="subtitle">Values</Text>
|
|
7
|
+
<View variant="card" gap="small">
|
|
8
|
+
<Text>Hello, {{ name }}</Text>
|
|
9
|
+
<Text>{{ genres.length }} favourite genres. The first is {{ genres[0] }}.</Text>
|
|
10
|
+
<Button variant="secondary" onClick="switchName">Change the name</Button>
|
|
11
|
+
</View>
|
|
12
|
+
</View>
|
|
13
|
+
|
|
14
|
+
<View gap="small">
|
|
15
|
+
<Text variant="subtitle">Expressions</Text>
|
|
16
|
+
<Text variant="caption" tone="muted">Maths, comparisons, ? : and ?? work. Calling a function doesn't: work the value out in the controller, as shout is here.</Text>
|
|
17
|
+
<View variant="card" gap="small">
|
|
18
|
+
<Text>{{ tickets }} {{ tickets === 1 ? 'ticket' : 'tickets' }} at Le {{ price }} each: Le {{ tickets * price }}</Text>
|
|
19
|
+
<Text>Stage name: {{ stageName ?? 'none yet' }}</Text>
|
|
20
|
+
<Text>Shouted: {{ shout }}!</Text>
|
|
21
|
+
</View>
|
|
22
|
+
</View>
|
|
23
|
+
|
|
24
|
+
<View gap="small">
|
|
25
|
+
<Text variant="subtitle">In attributes</Text>
|
|
26
|
+
<Text variant="caption" tone="muted">A binding can set any attribute, such as disabled, or the text on a button.</Text>
|
|
27
|
+
<View variant="card" direction="row" wrap gap="small">
|
|
28
|
+
<Button variant="secondary" onClick="addTicket">Add a ticket</Button>
|
|
29
|
+
<Button variant="secondary" onClick="removeTicket" disabled="{{ tickets === 0 }}">Remove one</Button>
|
|
30
|
+
<Button variant="secondary" onClick="toggleStageName">{{ stageName === null ? 'Give a stage name' : 'Drop the stage name' }}</Button>
|
|
31
|
+
</View>
|
|
32
|
+
</View>
|
|
33
|
+
|
|
34
|
+
<View gap="small">
|
|
35
|
+
<Text variant="subtitle">env</Text>
|
|
36
|
+
<Text variant="caption" tone="muted">Values in the dot's .env file. Anyone with the dot can read them, so never put a secret there.</Text>
|
|
37
|
+
<View variant="card">
|
|
38
|
+
<Text>{{ greeting }}</Text>
|
|
39
|
+
</View>
|
|
40
|
+
</View>
|
|
41
|
+
</View>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import state from './state';
|
|
2
|
+
|
|
3
|
+
export default definePage({
|
|
4
|
+
initialState: state,
|
|
5
|
+
mutations: {
|
|
6
|
+
// Sells five tickets for the show the button belongs to.
|
|
7
|
+
sell: (state, event: DotEvent<unknown, { id: string }>) => ({
|
|
8
|
+
shows: state.shows.map((show) =>
|
|
9
|
+
show.id === event.data.id ? { ...show, left: Math.max(0, show.left - 5) } : show,
|
|
10
|
+
),
|
|
11
|
+
}),
|
|
12
|
+
restock: (state) => ({ shows: state.shows.map((show) => ({ ...show, left: 20 })) }),
|
|
13
|
+
toggleSignedIn: (state) => ({ signedIn: !state.signedIn }),
|
|
14
|
+
// Changes the list's order. The key keeps each row's place right.
|
|
15
|
+
shuffle: (state) => ({ genres: [...state.genres.slice(1), state.genres[0]!] }),
|
|
16
|
+
},
|
|
17
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface Show {
|
|
2
|
+
id: string;
|
|
3
|
+
title: string;
|
|
4
|
+
city: string;
|
|
5
|
+
left: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
shows: [
|
|
10
|
+
{ id: 'freetown', title: 'Salone Sounds Live', city: 'Freetown', left: 120 },
|
|
11
|
+
{ id: 'bo', title: 'Palm-wine evening', city: 'Bo', left: 6 },
|
|
12
|
+
{ id: 'kenema', title: 'Gospel night', city: 'Kenema', left: 1 },
|
|
13
|
+
] as Show[],
|
|
14
|
+
genres: ['Palm-wine', 'Gumbe', 'Milo jazz', 'Afropop', 'Kriofusion'],
|
|
15
|
+
signedIn: false,
|
|
16
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<View>
|
|
2
|
+
<Text variant="title">If and For</Text>
|
|
3
|
+
<Text>If shows a part of the view only when its condition is true. For shows a part once for each item of a list.</Text>
|
|
4
|
+
|
|
5
|
+
<View gap="small">
|
|
6
|
+
<Text variant="subtitle">If and Else</Text>
|
|
7
|
+
<Text variant="caption" tone="muted">Else shows when the If before it doesn't.</Text>
|
|
8
|
+
<View variant="card" gap="small">
|
|
9
|
+
<If condition="{{ signedIn }}">
|
|
10
|
+
<Text>Welcome back, Mariama</Text>
|
|
11
|
+
</If>
|
|
12
|
+
<Else>
|
|
13
|
+
<Text tone="muted">You're not signed in</Text>
|
|
14
|
+
</Else>
|
|
15
|
+
<Button variant="secondary" onClick="toggleSignedIn">{{ signedIn ? 'Sign out' : 'Sign in' }}</Button>
|
|
16
|
+
</View>
|
|
17
|
+
</View>
|
|
18
|
+
|
|
19
|
+
<View gap="small">
|
|
20
|
+
<Text variant="subtitle">For, with ElseIf inside</Text>
|
|
21
|
+
<Text variant="caption" tone="muted">item names each show. key gives each a lasting id, so its row stays the same row when the list changes. ElseIf checks another condition when the one above is false.</Text>
|
|
22
|
+
<View variant="card" gap="medium">
|
|
23
|
+
<For each="{{ shows }}" item="show" key="id">
|
|
24
|
+
<View direction="row" align="center" gap="small">
|
|
25
|
+
<View grow gap="none">
|
|
26
|
+
<Text weight="medium">{{ show.title }}</Text>
|
|
27
|
+
<Text variant="caption" tone="muted">{{ show.city }}</Text>
|
|
28
|
+
</View>
|
|
29
|
+
<If condition="{{ show.left === 0 }}">
|
|
30
|
+
<Badge tone="danger">Sold out</Badge>
|
|
31
|
+
</If>
|
|
32
|
+
<ElseIf condition="{{ show.left < 10 }}">
|
|
33
|
+
<Badge tone="warning">{{ show.left }} left</Badge>
|
|
34
|
+
</ElseIf>
|
|
35
|
+
<Else>
|
|
36
|
+
<Badge tone="success">On sale</Badge>
|
|
37
|
+
</Else>
|
|
38
|
+
<Button variant="secondary" data-id="{{ show.id }}" onClick="sell" disabled="{{ show.left === 0 }}">Sell 5</Button>
|
|
39
|
+
</View>
|
|
40
|
+
</For>
|
|
41
|
+
<Button variant="secondary" onClick="restock">Restock every show</Button>
|
|
42
|
+
</View>
|
|
43
|
+
</View>
|
|
44
|
+
|
|
45
|
+
<View gap="small">
|
|
46
|
+
<Text variant="subtitle">For with index</Text>
|
|
47
|
+
<Text variant="caption" tone="muted">index counts from 0. A list of plain text has no id, so key="*this" uses the text itself.</Text>
|
|
48
|
+
<View variant="card" gap="small">
|
|
49
|
+
<For each="{{ genres }}" item="genre" index="position" key="*this">
|
|
50
|
+
<Text>{{ position + 1 }}. {{ genre }}</Text>
|
|
51
|
+
</For>
|
|
52
|
+
<Button variant="secondary" onClick="shuffle">Move the first to the end</Button>
|
|
53
|
+
</View>
|
|
54
|
+
</View>
|
|
55
|
+
</View>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import state from './state';
|
|
2
|
+
|
|
3
|
+
// What each handler below shows of its event.
|
|
4
|
+
function describe(handler: string, event: DotEvent) {
|
|
5
|
+
return {
|
|
6
|
+
handler,
|
|
7
|
+
type: event.type,
|
|
8
|
+
detail: JSON.stringify(event.detail),
|
|
9
|
+
data: JSON.stringify(event.data),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default definePage({
|
|
14
|
+
initialState: state,
|
|
15
|
+
mutations: {
|
|
16
|
+
// No detail: a tap is all there is to know.
|
|
17
|
+
countTap: (state, event: DotEvent) => ({
|
|
18
|
+
taps: state.taps + 1,
|
|
19
|
+
...describe('countTap', event),
|
|
20
|
+
}),
|
|
21
|
+
// `detail` is what the component sends: text for an Input...
|
|
22
|
+
setSong: (_state, event: DotEvent<{ value: string }>) => ({
|
|
23
|
+
song: event.detail.value,
|
|
24
|
+
...describe('setSong', event),
|
|
25
|
+
}),
|
|
26
|
+
// ...a number for a Slider...
|
|
27
|
+
setVolume: (_state, event: DotEvent<{ value: number }>) => ({
|
|
28
|
+
volume: event.detail.value,
|
|
29
|
+
...describe('setVolume', event),
|
|
30
|
+
}),
|
|
31
|
+
// ...and checked for a Switch.
|
|
32
|
+
setLoud: (_state, event: DotEvent<{ checked: boolean }>) => ({
|
|
33
|
+
loud: event.detail.checked,
|
|
34
|
+
...describe('setLoud', event),
|
|
35
|
+
}),
|
|
36
|
+
// `data` holds the element's data- attributes, as text.
|
|
37
|
+
play: (_state, event: DotEvent<unknown, { artist: string; year: string }>) => ({
|
|
38
|
+
song: `${event.data.artist}, ${event.data.year}`,
|
|
39
|
+
...describe('play', event),
|
|
40
|
+
}),
|
|
41
|
+
},
|
|
42
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<View>
|
|
2
|
+
<Text variant="title">Events</Text>
|
|
3
|
+
<Text>An attribute such as onClick or onChange names the handler to run. The handler gets the state and the event.</Text>
|
|
4
|
+
|
|
5
|
+
<View gap="small">
|
|
6
|
+
<Text variant="subtitle">The last event</Text>
|
|
7
|
+
<View variant="card" gap="none">
|
|
8
|
+
<If condition="{{ handler }}">
|
|
9
|
+
<DetailRow label="Handler" value="{{ handler }}" />
|
|
10
|
+
<DetailRow label="event.type" value="{{ type }}" />
|
|
11
|
+
<DetailRow label="event.detail" value="{{ detail }}" />
|
|
12
|
+
<DetailRow label="event.data" value="{{ data }}" />
|
|
13
|
+
</If>
|
|
14
|
+
<Else>
|
|
15
|
+
<Text tone="muted">Use anything below to see its event here.</Text>
|
|
16
|
+
</Else>
|
|
17
|
+
</View>
|
|
18
|
+
</View>
|
|
19
|
+
|
|
20
|
+
<View gap="small">
|
|
21
|
+
<Text variant="subtitle">Taps</Text>
|
|
22
|
+
<Text variant="caption" tone="muted">Button raises click. View, ListItem, Link and Chip raise tap.</Text>
|
|
23
|
+
<View variant="card" direction="row" align="center" gap="small">
|
|
24
|
+
<Button variant="secondary" onClick="countTap">Tap me</Button>
|
|
25
|
+
<View variant="card" grow onTap="countTap">
|
|
26
|
+
<Text>Or tap this box</Text>
|
|
27
|
+
</View>
|
|
28
|
+
<Text numeric>{{ taps }}</Text>
|
|
29
|
+
</View>
|
|
30
|
+
</View>
|
|
31
|
+
|
|
32
|
+
<View gap="small">
|
|
33
|
+
<Text variant="subtitle">event.detail</Text>
|
|
34
|
+
<Text variant="caption" tone="muted">What the component sends, such as the text typed or the switch's new state.</Text>
|
|
35
|
+
<View variant="card">
|
|
36
|
+
<Input label="Song" placeholder="Exodus" value="{{ song }}" onChange="setSong" />
|
|
37
|
+
<Slider label="Volume" min="0" max="10" showValue value="{{ volume }}" onChange="setVolume" />
|
|
38
|
+
<Switch label="Loud" checked="{{ loud }}" onChange="setLoud" />
|
|
39
|
+
</View>
|
|
40
|
+
</View>
|
|
41
|
+
|
|
42
|
+
<View gap="small">
|
|
43
|
+
<Text variant="subtitle">event.data</Text>
|
|
44
|
+
<Text variant="caption" tone="muted">The data- attributes of the element, such as data-artist. They tell one handler which item was used. Their values arrive as text.</Text>
|
|
45
|
+
<View variant="card" direction="row" wrap gap="small">
|
|
46
|
+
<Button variant="secondary" data-artist="Drizilik" data-year="2021" onClick="play">Exodus</Button>
|
|
47
|
+
<Button variant="secondary" data-artist="ApreeL" data-year="2025" onClick="play">Control</Button>
|
|
48
|
+
<Button variant="secondary" data-artist="Emmerson" data-year="2004" onClick="play">Borbor Bele</Button>
|
|
49
|
+
</View>
|
|
50
|
+
</View>
|
|
51
|
+
</View>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { HookRun } from './state';
|
|
2
|
+
import state from './state';
|
|
3
|
+
|
|
4
|
+
// Outside the page, so it outlives each copy of it while the dot runs.
|
|
5
|
+
let lastClosed = '';
|
|
6
|
+
|
|
7
|
+
function ran(runs: readonly HookRun[], hook: string): HookRun[] {
|
|
8
|
+
return [...runs, { id: runs.length + 1, hook }];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default definePage({
|
|
12
|
+
initialState: state,
|
|
13
|
+
hooks: {
|
|
14
|
+
// Runs once, when the page opens, with the options it opened with.
|
|
15
|
+
onLoad(options) {
|
|
16
|
+
this.setState({ lastClosed, runs: ran([], `onLoad ${JSON.stringify(options)}`) });
|
|
17
|
+
},
|
|
18
|
+
// Runs each time the page comes into view: after onLoad, and when a page above it closes.
|
|
19
|
+
onShow() {
|
|
20
|
+
this.setState((current) => ({ runs: ran(current.runs, 'onShow') }));
|
|
21
|
+
},
|
|
22
|
+
// Runs when another page opens on top, or the dot goes into the background.
|
|
23
|
+
onHide() {
|
|
24
|
+
this.setState((current) => ({ runs: ran(current.runs, 'onHide') }));
|
|
25
|
+
},
|
|
26
|
+
// Runs once, when the page closes. Its state goes with it.
|
|
27
|
+
onUnload() {
|
|
28
|
+
lastClosed = new Date().toLocaleTimeString('en-GB');
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
actions: {
|
|
32
|
+
openAnother() {
|
|
33
|
+
this.navigation.push('basics/state');
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<View>
|
|
2
|
+
<Text variant="title">Page hooks</Text>
|
|
3
|
+
<Text>Hooks run at points in a page's life, such as when it opens. Use them to load data or to save it.</Text>
|
|
4
|
+
|
|
5
|
+
<View gap="small">
|
|
6
|
+
<Text variant="subtitle">The hooks this page ran, in order</Text>
|
|
7
|
+
<View variant="card" gap="small">
|
|
8
|
+
<For each="{{ runs }}" item="run" key="id">
|
|
9
|
+
<Text>{{ run.id }}. {{ run.hook }}</Text>
|
|
10
|
+
</For>
|
|
11
|
+
</View>
|
|
12
|
+
<Text variant="caption" tone="muted">Open another page, then come back: this page runs onHide, then onShow.</Text>
|
|
13
|
+
<Button variant="secondary" onClick="openAnother">Open another page</Button>
|
|
14
|
+
</View>
|
|
15
|
+
|
|
16
|
+
<View gap="small">
|
|
17
|
+
<Text variant="subtitle">onUnload</Text>
|
|
18
|
+
<View variant="card">
|
|
19
|
+
<If condition="{{ lastClosed }}">
|
|
20
|
+
<Text>This page last closed at {{ lastClosed }}</Text>
|
|
21
|
+
</If>
|
|
22
|
+
<Else>
|
|
23
|
+
<Text tone="muted">Go back, then open this page again. It says when it closed.</Text>
|
|
24
|
+
</Else>
|
|
25
|
+
</View>
|
|
26
|
+
</View>
|
|
27
|
+
|
|
28
|
+
<View gap="small">
|
|
29
|
+
<Text variant="subtitle">The dot's hooks</Text>
|
|
30
|
+
<Text variant="caption" tone="muted">dot.ts can have hooks too: onLaunch runs once when the dot starts, and onError gets any error a page doesn't catch.</Text>
|
|
31
|
+
</View>
|
|
32
|
+
</View>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import state from './state';
|
|
2
|
+
|
|
3
|
+
export default definePage({
|
|
4
|
+
initialState: state,
|
|
5
|
+
hooks: {
|
|
6
|
+
// Options come from the page that opened this one, as text.
|
|
7
|
+
onLoad(options) {
|
|
8
|
+
const depth = Number(options.depth ?? '1') + 1;
|
|
9
|
+
const from = options.trail ?? 'Home';
|
|
10
|
+
this.setState({ depth, from, trail: `${from} › ${depth}`, options: JSON.stringify(options) });
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
actions: {
|
|
14
|
+
openAnother(state) {
|
|
15
|
+
this.navigation.push('basics/navigation', { depth: String(state.depth), trail: state.trail });
|
|
16
|
+
},
|
|
17
|
+
replaceThis(state) {
|
|
18
|
+
this.navigation.replace('basics/navigation', {
|
|
19
|
+
depth: String(state.depth - 1),
|
|
20
|
+
trail: state.from,
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
back() {
|
|
24
|
+
this.navigation.back();
|
|
25
|
+
},
|
|
26
|
+
backTwo() {
|
|
27
|
+
this.navigation.back(2);
|
|
28
|
+
},
|
|
29
|
+
home() {
|
|
30
|
+
this.navigation.reset('index');
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<View>
|
|
2
|
+
<Text variant="caption" tone="muted">{{ trail }}</Text>
|
|
3
|
+
<Text variant="title">Navigation</Text>
|
|
4
|
+
<Text>Actions open pages with this.navigation. Each new page opens on top, and back returns to the one below. A dot can have {{ maxDepth }} pages open at once.</Text>
|
|
5
|
+
|
|
6
|
+
<View variant="card" gap="small">
|
|
7
|
+
<Text>This is page {{ depth }} of {{ maxDepth }}</Text>
|
|
8
|
+
<Text variant="caption" tone="muted">It opened with {{ options }}</Text>
|
|
9
|
+
</View>
|
|
10
|
+
|
|
11
|
+
<View gap="small">
|
|
12
|
+
<Text variant="subtitle">push</Text>
|
|
13
|
+
<Text variant="caption" tone="muted">Opens a page on top, with options it reads in onLoad.</Text>
|
|
14
|
+
<Button onClick="openAnother" disabled="{{ depth >= maxDepth }}">Open another</Button>
|
|
15
|
+
</View>
|
|
16
|
+
|
|
17
|
+
<View gap="small">
|
|
18
|
+
<Text variant="subtitle">replace</Text>
|
|
19
|
+
<Text variant="caption" tone="muted">Opens a page in this one's place, so back skips this one.</Text>
|
|
20
|
+
<Button variant="secondary" onClick="replaceThis">Replace this one</Button>
|
|
21
|
+
</View>
|
|
22
|
+
|
|
23
|
+
<View gap="small">
|
|
24
|
+
<Text variant="subtitle">back</Text>
|
|
25
|
+
<Text variant="caption" tone="muted">Closes this page, or as many as you ask. On the first page, it closes the dot.</Text>
|
|
26
|
+
<View direction="row" gap="small">
|
|
27
|
+
<Button variant="secondary" onClick="back">Back</Button>
|
|
28
|
+
<Button variant="secondary" onClick="backTwo" disabled="{{ depth < 3 }}">Back two</Button>
|
|
29
|
+
</View>
|
|
30
|
+
</View>
|
|
31
|
+
|
|
32
|
+
<View gap="small">
|
|
33
|
+
<Text variant="subtitle">reset</Text>
|
|
34
|
+
<Text variant="caption" tone="muted">Closes every page and opens one, such as the home page.</Text>
|
|
35
|
+
<Button variant="secondary" onClick="home">Start over</Button>
|
|
36
|
+
</View>
|
|
37
|
+
</View>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<View>
|
|
2
|
+
<Text variant="title">State, mutations and actions</Text>
|
|
3
|
+
<Text>A page keeps its data in state.ts. Handlers in controller.ts change it, and the view shows the change. Here, the crowd wants one more song.</Text>
|
|
4
|
+
|
|
5
|
+
<View variant="card" gap="small">
|
|
6
|
+
<Text variant="subtitle">{{ count }} of {{ limit }} {{ title }}</Text>
|
|
7
|
+
<If condition="{{ count >= limit }}">
|
|
8
|
+
<Text>Encore! The band comes back on</Text>
|
|
9
|
+
</If>
|
|
10
|
+
<ElseIf condition="{{ count > 0 }}">
|
|
11
|
+
<Text>{{ limit - count }} more and the band comes back</Text>
|
|
12
|
+
</ElseIf>
|
|
13
|
+
<Else>
|
|
14
|
+
<Text>Tap Cheer to start</Text>
|
|
15
|
+
</Else>
|
|
16
|
+
<View direction="row" wrap gap="small">
|
|
17
|
+
<Button onClick="increment" disabled="{{ count >= limit }}">Cheer</Button>
|
|
18
|
+
<Button variant="secondary" onClick="reset" disabled="{{ count === 0 }}">Reset</Button>
|
|
19
|
+
<Button variant="secondary" onClick="fillUp" disabled="{{ count >= limit }}">Whole crowd</Button>
|
|
20
|
+
<Button variant="secondary" onClick="undo" disabled="{{ count === 0 }}">Undo</Button>
|
|
21
|
+
</View>
|
|
22
|
+
</View>
|
|
23
|
+
|
|
24
|
+
<View gap="small">
|
|
25
|
+
<Text variant="subtitle">Mutations</Text>
|
|
26
|
+
<Text>Cheer and Reset are mutations. A mutation gets the state and returns the changes to make, such as { count: 1 }. It can't wait for anything.</Text>
|
|
27
|
+
</View>
|
|
28
|
+
|
|
29
|
+
<View gap="small">
|
|
30
|
+
<Text variant="subtitle">Actions</Text>
|
|
31
|
+
<Text>Whole crowd and Undo are actions. An action can take several steps, call other handlers with this.mutations and this.actions, and wait for Dash.</Text>
|
|
32
|
+
<Text>Whole crowd calls the Cheer mutation until the crowd is full. Undo calls this.setState with a function, which gets the latest state.</Text>
|
|
33
|
+
</View>
|
|
34
|
+
|
|
35
|
+
<View gap="small">
|
|
36
|
+
<Text variant="subtitle">Each cheer, newest first</Text>
|
|
37
|
+
<View variant="card" gap="small">
|
|
38
|
+
<For each="{{ taps }}" index="position" item="tap" key="id">
|
|
39
|
+
<Text>{{ position + 1 }}. Cheer #{{ tap.id }}</Text>
|
|
40
|
+
</For>
|
|
41
|
+
<If condition="{{ taps.length === 0 }}">
|
|
42
|
+
<Text variant="caption" tone="muted">No cheers yet</Text>
|
|
43
|
+
</If>
|
|
44
|
+
</View>
|
|
45
|
+
</View>
|
|
46
|
+
</View>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
<View>
|
|
2
2
|
<Text variant="title">Carousel</Text>
|
|
3
|
-
<Text>A
|
|
3
|
+
<Text>A Carousel shows one slide at a time. Swipe, or tap a dot.</Text>
|
|
4
4
|
|
|
5
5
|
<View gap="small">
|
|
6
|
-
<Text variant="
|
|
7
|
-
<
|
|
6
|
+
<Text variant="subtitle">autoplay, loop and effect</Text>
|
|
7
|
+
<Text variant="caption" tone="muted">Gen Z artists. The slides move on their own every 3 seconds, start over at the end, and pause when you touch them. effect="scale" shrinks the slides beside the one in view.</Text>
|
|
8
|
+
<Carousel autoplay loop interval="3000" gap="medium" effect="scale" indicator="dots">
|
|
8
9
|
<For each="{{ artists }}" item="artist" key="id">
|
|
9
10
|
<View variant="card" align="center" gap="medium">
|
|
10
11
|
<If condition="{{ artist.photo }}">
|
|
@@ -21,8 +22,9 @@
|
|
|
21
22
|
</View>
|
|
22
23
|
|
|
23
24
|
<View gap="small">
|
|
24
|
-
<Text variant="
|
|
25
|
-
<
|
|
25
|
+
<Text variant="subtitle">index and onChange</Text>
|
|
26
|
+
<Text variant="caption" tone="muted">How Salone music grew, from palm-wine to Gen Z. The page sets the slide with index, and onChange tells it when you swipe. The buttons move the slides, so indicator="none" hides the dots.</Text>
|
|
27
|
+
<Carousel index="{{ chapter }}" indicator="none" effect="slide" gap="small" padding="small" onChange="showChapter">
|
|
26
28
|
<For each="{{ chapters }}" item="card" key="title">
|
|
27
29
|
<View variant="card" align="center" gap="medium">
|
|
28
30
|
<Image src="statics/logo.png" alt="" width="48" height="48" />
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
<Text>Show that something is loading, how far it has gone, and how it ended.</Text>
|
|
4
4
|
|
|
5
5
|
<View gap="small">
|
|
6
|
-
<Text variant="
|
|
6
|
+
<Text variant="subtitle">Spinner</Text>
|
|
7
|
+
<Text variant="caption" tone="muted">While something loads, in three sizes.</Text>
|
|
7
8
|
<View variant="card" direction="row" gap="large" align="center">
|
|
8
9
|
<Spinner size="small" />
|
|
9
10
|
<Spinner />
|
|
@@ -12,7 +13,8 @@
|
|
|
12
13
|
</View>
|
|
13
14
|
|
|
14
15
|
<View gap="small">
|
|
15
|
-
<Text variant="
|
|
16
|
+
<Text variant="subtitle">Skeleton</Text>
|
|
17
|
+
<Text variant="caption" tone="muted">Shows the shape of what is loading: lines of text, a circle or a box.</Text>
|
|
16
18
|
<View variant="card">
|
|
17
19
|
<If condition="{{ loaded }}">
|
|
18
20
|
<View direction="row" align="center" gap="large">
|
|
@@ -27,7 +29,7 @@
|
|
|
27
29
|
<Else>
|
|
28
30
|
<View direction="row" align="center" gap="large">
|
|
29
31
|
<Skeleton shape="circle" />
|
|
30
|
-
<Skeleton lines="2" />
|
|
32
|
+
<Skeleton shape="text" lines="2" />
|
|
31
33
|
</View>
|
|
32
34
|
<Skeleton shape="box" height="80" />
|
|
33
35
|
</Else>
|
|
@@ -36,15 +38,19 @@
|
|
|
36
38
|
</View>
|
|
37
39
|
|
|
38
40
|
<View gap="small">
|
|
39
|
-
<Text variant="
|
|
40
|
-
<
|
|
41
|
+
<Text variant="subtitle">Toast</Text>
|
|
42
|
+
<Text variant="caption" tone="muted">A short message over the page that goes on its own. The offline one stays for 6 seconds.</Text>
|
|
43
|
+
<View direction="row" wrap gap="small">
|
|
41
44
|
<Button variant="secondary" data-message="Added to your library" data-tone="success" onClick="showToast">Add a song</Button>
|
|
42
45
|
<Button variant="secondary" data-message="You're offline. Only downloads will play." data-tone="warning" data-duration="6000" onClick="showToast">Go offline</Button>
|
|
46
|
+
<Button variant="secondary" data-message="A new song from Boii" data-tone="info" onClick="showToast">New song</Button>
|
|
47
|
+
<Button variant="secondary" data-message="That song can't play here" data-tone="danger" onClick="showToast">Fail</Button>
|
|
43
48
|
</View>
|
|
44
49
|
</View>
|
|
45
50
|
|
|
46
51
|
<View gap="small">
|
|
47
|
-
<Text variant="
|
|
52
|
+
<Text variant="subtitle">ProgressBar</Text>
|
|
53
|
+
<Text variant="caption" tone="muted">How far something has gone, from 0 to 100, such as an album download.</Text>
|
|
48
54
|
<View variant="card">
|
|
49
55
|
<ProgressBar value="{{ progress }}" />
|
|
50
56
|
<Text>{{ progress }}% downloaded</Text>
|
|
@@ -56,7 +62,8 @@
|
|
|
56
62
|
</View>
|
|
57
63
|
|
|
58
64
|
<View gap="small">
|
|
59
|
-
<Text variant="
|
|
65
|
+
<Text variant="subtitle">A busy Button</Text>
|
|
66
|
+
<Text variant="caption" tone="muted">loading shows a spinner, and the button ignores taps.</Text>
|
|
60
67
|
<View variant="card">
|
|
61
68
|
<Button loading="{{ busy }}">{{ busy ? 'Paying…' : 'Pay Le 300 for two tickets' }}</Button>
|
|
62
69
|
<Switch label="Busy" checked="{{ busy }}" onChange="toggleBusy" />
|
|
@@ -64,7 +71,8 @@
|
|
|
64
71
|
</View>
|
|
65
72
|
|
|
66
73
|
<View gap="small">
|
|
67
|
-
<Text variant="
|
|
74
|
+
<Text variant="subtitle">Notice</Text>
|
|
75
|
+
<Text variant="caption" tone="muted">A message that stays in the page, in a tone.</Text>
|
|
68
76
|
<Notice title="Heads up">Doors open at 7 pm, and the music starts at 8.</Notice>
|
|
69
77
|
<Notice tone="info" title="New">Tickets for gospel night in Kenema are on sale.</Notice>
|
|
70
78
|
<Notice tone="success" title="Booked">Two tickets for Salone Sounds Live.</Notice>
|
|
@@ -73,7 +81,8 @@
|
|
|
73
81
|
</View>
|
|
74
82
|
|
|
75
83
|
<View gap="small">
|
|
76
|
-
<Text variant="
|
|
84
|
+
<Text variant="subtitle">Badge</Text>
|
|
85
|
+
<Text variant="caption" tone="muted">A short status.</Text>
|
|
77
86
|
<View direction="row" wrap gap="small">
|
|
78
87
|
<Badge>Demo</Badge>
|
|
79
88
|
<Badge tone="info">New release</Badge>
|
|
@@ -2,13 +2,13 @@ import type { TicketType } from './state';
|
|
|
2
2
|
import state, { SHOWS, TICKETS } from './state';
|
|
3
3
|
|
|
4
4
|
type Typed = DotEvent<{ value: string }>;
|
|
5
|
+
type Toggled = DotEvent<{ checked: boolean }>;
|
|
5
6
|
|
|
6
7
|
// "2" tickets of a Le 1,200 type -> "Le 2,400"
|
|
7
8
|
function total(tickets: string, ticket: TicketType): string {
|
|
8
9
|
const leones = (Number(tickets) || 0) * TICKETS[ticket].price;
|
|
9
10
|
return `Le ${leones.toLocaleString('en-US')}`;
|
|
10
11
|
}
|
|
11
|
-
type Toggled = DotEvent<{ checked: boolean }>;
|
|
12
12
|
|
|
13
13
|
export default definePage({
|
|
14
14
|
initialState: state,
|
|
@@ -25,6 +25,9 @@ export default definePage({
|
|
|
25
25
|
total: total(event.detail.value, state.ticket),
|
|
26
26
|
}),
|
|
27
27
|
setShoutOut: (_state, event: Typed) => ({ shoutOut: event.detail.value }),
|
|
28
|
+
setPromo: (_state, event: Typed) => ({ promo: event.detail.value }),
|
|
29
|
+
setChairs: (_state, event: DotEvent<{ value: number }>) => ({ chairs: event.detail.value }),
|
|
30
|
+
setTip: (_state, event: DotEvent<{ value: number }>) => ({ tip: event.detail.value }),
|
|
28
31
|
setTicket: (state, event: DotEvent<{ value: TicketType }>) => ({
|
|
29
32
|
ticket: event.detail.value,
|
|
30
33
|
ticketName: TICKETS[event.detail.value].name,
|