@monimesl/dot-cli 1.0.0-beta.2 → 1.0.0-beta.4
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/README.md +22 -9
- package/dist/cli.js +13 -11
- package/dist/cli.js.map +1 -1
- package/dist/templates/showcase/.env +2 -2
- package/dist/templates/showcase/dot.ts +2 -1
- package/dist/templates/showcase/pages/basics/bars/controller.ts +2 -2
- package/dist/templates/showcase/pages/basics/bars/view.dml +2 -1
- package/dist/templates/showcase/pages/basics/bindings/state.ts +2 -2
- package/dist/templates/showcase/pages/basics/bindings/view.dml +2 -2
- package/dist/templates/showcase/pages/basics/colors/controller.ts +1 -1
- package/dist/templates/showcase/pages/basics/concert/view.dml +1 -1
- package/dist/templates/showcase/pages/basics/control-flow/controller.ts +1 -1
- package/dist/templates/showcase/pages/basics/control-flow/view.dml +1 -1
- package/dist/templates/showcase/pages/basics/events/controller.ts +1 -1
- package/dist/templates/showcase/pages/basics/events/view.dml +1 -1
- package/dist/templates/showcase/pages/basics/hooks/controller.ts +2 -1
- package/dist/templates/showcase/pages/basics/hooks/view.dml +2 -2
- package/dist/templates/showcase/pages/basics/navigation/controller.ts +1 -0
- package/dist/templates/showcase/pages/basics/navigation/view.dml +1 -1
- package/dist/templates/showcase/pages/basics/pick-genre/controller.ts +3 -3
- package/dist/templates/showcase/pages/basics/share/view.dml +2 -2
- package/dist/templates/showcase/pages/basics/state/controller.ts +9 -0
- package/dist/templates/showcase/pages/basics/state/state.ts +3 -0
- package/dist/templates/showcase/pages/components/carousel/view.dml +2 -2
- package/dist/templates/showcase/pages/components/feedback/controller.ts +2 -1
- package/dist/templates/showcase/pages/components/feedback/state.ts +2 -2
- package/dist/templates/showcase/pages/components/feedback/view.dml +2 -2
- package/dist/templates/showcase/pages/components/forms/controller.ts +2 -2
- package/dist/templates/showcase/pages/components/forms/state.ts +1 -1
- package/dist/templates/showcase/pages/components/forms/view.dml +5 -5
- package/dist/templates/showcase/pages/components/icons/controller.ts +1 -0
- package/dist/templates/showcase/pages/components/icons/state.ts +1 -1
- package/dist/templates/showcase/pages/components/images/controller.ts +1 -1
- package/dist/templates/showcase/pages/components/images/state.ts +1 -1
- package/dist/templates/showcase/pages/components/images/view.dml +4 -4
- package/dist/templates/showcase/pages/components/layout/controller.ts +3 -1
- package/dist/templates/showcase/pages/components/layout/view.dml +5 -5
- package/dist/templates/showcase/pages/components/lists/view.dml +7 -7
- package/dist/templates/showcase/pages/components/money/controller.ts +1 -1
- package/dist/templates/showcase/pages/components/money/view.dml +2 -2
- package/dist/templates/showcase/pages/components/reading/state.ts +2 -2
- package/dist/templates/showcase/pages/components/sheets/controller.ts +1 -1
- package/dist/templates/showcase/pages/components/sheets/view.dml +1 -1
- package/dist/templates/showcase/pages/components/styles/view.dml +3 -3
- package/dist/templates/showcase/pages/components/tabs/state.ts +2 -2
- package/dist/templates/showcase/pages/components/tabs/view.dml +2 -2
- package/dist/templates/showcase/pages/components/text/view.dml +3 -3
- package/dist/templates/showcase/pages/dash/account/controller.ts +3 -0
- package/dist/templates/showcase/pages/dash/account/view.dml +2 -2
- package/dist/templates/showcase/pages/dash/cache/controller.ts +3 -0
- package/dist/templates/showcase/pages/dash/calls/controller.ts +3 -2
- package/dist/templates/showcase/pages/dash/contacts/controller.ts +1 -0
- package/dist/templates/showcase/pages/dash/crypto/controller.ts +2 -0
- package/dist/templates/showcase/pages/dash/crypto/view.dml +1 -1
- package/dist/templates/showcase/pages/dash/files/controller.ts +6 -1
- package/dist/templates/showcase/pages/dash/files/view.dml +1 -1
- package/dist/templates/showcase/pages/dash/media/controller.ts +7 -1
- package/dist/templates/showcase/pages/dash/media/state.ts +2 -0
- package/dist/templates/showcase/pages/dash/network/controller.ts +5 -1
- package/dist/templates/showcase/pages/dash/network/view.dml +1 -1
- package/dist/templates/showcase/pages/dash/payments/cases.ts +3 -3
- package/dist/templates/showcase/pages/dash/payments/controller.ts +6 -0
- package/dist/templates/showcase/pages/dash/payments/view.dml +1 -1
- package/dist/templates/showcase/pages/dash/secrets/controller.ts +3 -0
- package/dist/templates/showcase/pages/dash/system/controller.ts +5 -0
- package/dist/templates/showcase/pages/dash/system/view.dml +4 -4
- package/dist/templates/showcase/pages/dash/ui/controller.ts +6 -1
- package/dist/templates/showcase/pages/index/controller.ts +1 -0
- package/dist/templates/showcase/pages/index/state.ts +3 -3
- package/dist/templates/starter/.env +2 -2
- package/dist/templates/starter/dot.ts +1 -0
- package/dist/templates/starter/pages/index/controller.ts +2 -0
- package/dist/templates/starter/pages/index/state.ts +2 -0
- package/dist/templates/starter/pages/index/view.dml +2 -1
- package/package.json +6 -6
|
@@ -3,7 +3,7 @@ import { logger } from '@monimesl/dot-runtime';
|
|
|
3
3
|
import { swatchColors } from './pages/basics/colors/palette';
|
|
4
4
|
|
|
5
5
|
export default defineDot({
|
|
6
|
-
//
|
|
6
|
+
// Each page is a folder under pages/, here in the home page's order. The dot opens on the first.
|
|
7
7
|
pages: [
|
|
8
8
|
'index',
|
|
9
9
|
// How a page works.
|
|
@@ -57,5 +57,6 @@ export default defineDot({
|
|
|
57
57
|
},
|
|
58
58
|
},
|
|
59
59
|
},
|
|
60
|
+
// logger() writes each page load, event, navigation and state change to the console.
|
|
60
61
|
plugins: [logger()],
|
|
61
62
|
});
|
|
@@ -24,8 +24,8 @@ export default definePage({
|
|
|
24
24
|
},
|
|
25
25
|
togglePainted(state) {
|
|
26
26
|
const painted = !state.painted;
|
|
27
|
-
// A pale sky
|
|
28
|
-
// fields and quieter text follow the background, unless the page sets those too.
|
|
27
|
+
// A pale sky in light mode, the night over Freetown in dark. Undefined puts the theme's back.
|
|
28
|
+
// Cards, fields and quieter text follow the background, unless the page sets those too.
|
|
29
29
|
if (painted) {
|
|
30
30
|
this.setColors({ background: { light: '#E3F2FD', dark: '#0B1A2E' } });
|
|
31
31
|
} else {
|
|
@@ -16,12 +16,13 @@
|
|
|
16
16
|
<Button variant="secondary" onClick="toggleColors">{{ colored ? 'Plain bar' : 'Green bar' }}</Button>
|
|
17
17
|
<Button variant="secondary" onClick="toggleNavigationBar">{{ navigationBarHidden ? 'Show the bar' : 'Hide the bar' }}</Button>
|
|
18
18
|
</View>
|
|
19
|
+
<Text variant="caption" tone="muted">A title can be up to 60 characters. With the bar hidden, Dash still shows a capsule at the top right with the dot's menu, so keep that corner free.</Text>
|
|
19
20
|
</View>
|
|
20
21
|
</View>
|
|
21
22
|
|
|
22
23
|
<View gap="small">
|
|
23
24
|
<Text variant="subtitle">setColors</Text>
|
|
24
|
-
<Text variant="caption" tone="muted">configs.colors or setColors give a page its own colours, for light and dark, such as its background. Dash
|
|
25
|
+
<Text variant="caption" tone="muted">configs.colors or setColors give a page its own colours, for light and dark, such as its background. Dash picks text and bar colours that read on it. The Page colours page has more.</Text>
|
|
25
26
|
<View variant="card">
|
|
26
27
|
<Button variant="secondary" onClick="togglePainted">{{ painted ? 'Theme background' : 'Sky background' }}</Button>
|
|
27
28
|
</View>
|
|
@@ -3,11 +3,11 @@ export default {
|
|
|
3
3
|
syntax: '{{ name }}',
|
|
4
4
|
name: 'Mariama',
|
|
5
5
|
stageName: null as string | null,
|
|
6
|
-
//
|
|
6
|
+
// In leones (SLE), the new leone of 2022.
|
|
7
7
|
price: 150,
|
|
8
8
|
tickets: 4,
|
|
9
9
|
genres: ['kriofusion', 'palm-wine', 'gumbe'],
|
|
10
|
-
//
|
|
10
|
+
// A binding reads only the page's state, so a value from .env goes in it first.
|
|
11
11
|
greeting: env.GREETING,
|
|
12
12
|
// Worked out in the controller, since a binding can't call a function.
|
|
13
13
|
shout: 'MARIAMA',
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
<View gap="small">
|
|
15
15
|
<Text variant="subtitle">Expressions</Text>
|
|
16
|
-
<Text variant="caption" tone="muted">Maths, comparisons, ? : and ?? work.
|
|
16
|
+
<Text variant="caption" tone="muted">Maths, comparisons, ? : and ?? work. A binding can't call a function, so work the value out in the controller, as shout is here.</Text>
|
|
17
17
|
<View variant="card" gap="small">
|
|
18
18
|
<Text>{{ tickets }} {{ tickets === 1 ? 'ticket' : 'tickets' }} at Le {{ price }} each: Le {{ tickets * price }}</Text>
|
|
19
19
|
<Text>Stage name: {{ stageName ?? 'none yet' }}</Text>
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
|
|
34
34
|
<View gap="small">
|
|
35
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>
|
|
36
|
+
<Text variant="caption" tone="muted">Values in the dot's .env file, copied into state.ts to show here. Anyone with the dot can read them, so never put a secret there.</Text>
|
|
37
37
|
<View variant="card">
|
|
38
38
|
<Text>{{ greeting }}</Text>
|
|
39
39
|
</View>
|
|
@@ -31,7 +31,7 @@ export default definePage({
|
|
|
31
31
|
},
|
|
32
32
|
useCustom(state) {
|
|
33
33
|
const light = state.customLight.trim();
|
|
34
|
-
// One colour is enough
|
|
34
|
+
// One colour is enough. It's used in dark mode too.
|
|
35
35
|
const dark = state.customDark.trim() || light;
|
|
36
36
|
if (!HEX_COLOR.test(light) || !HEX_COLOR.test(dark)) {
|
|
37
37
|
this.setState({ customError: 'Write a colour as # and six digits, such as #FFF3E0' });
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<Notice tone="info">Opened for {{ buyer }}. buyer isn't in share's options, so a shared link leaves it out.</Notice>
|
|
11
11
|
</If>
|
|
12
12
|
<Else>
|
|
13
|
-
<Notice tone="success">Opened from a link
|
|
13
|
+
<Notice tone="success">Opened from a link. It carried the concert and nothing else.</Notice>
|
|
14
14
|
</Else>
|
|
15
15
|
<Text variant="caption" tone="muted">Tap ••• then Share. The link opens this concert.</Text>
|
|
16
16
|
</If>
|
|
@@ -12,7 +12,7 @@ export default definePage({
|
|
|
12
12
|
}),
|
|
13
13
|
restock: (state) => ({ shows: state.shows.map((show) => ({ ...show, left: 20 })) }),
|
|
14
14
|
toggleSignedIn: (state) => ({ signedIn: !state.signedIn }),
|
|
15
|
-
// Changes the list's order. The key
|
|
15
|
+
// Changes the list's order. The For's key lets each row move with its item.
|
|
16
16
|
shuffle: (state) => ({ genres: [...state.genres.slice(1), state.genres[0]!] }),
|
|
17
17
|
},
|
|
18
18
|
});
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
<View gap="small">
|
|
20
20
|
<Text variant="subtitle">For, with ElseIf inside</Text>
|
|
21
|
-
<Text variant="caption" tone="muted">item names each show. key
|
|
21
|
+
<Text variant="caption" tone="muted">item names each show. key names the field that tells the shows apart, so each row stays with its show when the list changes. ElseIf checks another condition when the one above is false.</Text>
|
|
22
22
|
<View variant="card" gap="medium">
|
|
23
23
|
<For each="{{ shows }}" item="show" key="id">
|
|
24
24
|
<View direction="row" align="center" gap="small">
|
|
@@ -14,7 +14,7 @@ export default definePage({
|
|
|
14
14
|
initialState: state,
|
|
15
15
|
configs: { navigationBar: { title: 'Events' } },
|
|
16
16
|
mutations: {
|
|
17
|
-
//
|
|
17
|
+
// A tap has no detail. It only says the tap happened.
|
|
18
18
|
countTap: (state, event: DotEvent) => ({
|
|
19
19
|
taps: state.taps + 1,
|
|
20
20
|
...describe('countTap', event),
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
<View gap="small">
|
|
21
21
|
<Text variant="subtitle">Taps</Text>
|
|
22
|
-
<Text variant="caption" tone="muted">Button raises click. View, ListItem, Link and Chip raise tap.</Text>
|
|
22
|
+
<Text variant="caption" tone="muted">A Button raises click, so it takes onClick. View, ListItem, Link and Chip raise tap, so they take onTap.</Text>
|
|
23
23
|
<View variant="card" direction="row" align="center" gap="small">
|
|
24
24
|
<Button variant="secondary" onClick="countTap">Tap me</Button>
|
|
25
25
|
<View variant="card" grow onTap="countTap">
|
|
@@ -16,7 +16,8 @@ export default definePage({
|
|
|
16
16
|
onLoad(options) {
|
|
17
17
|
this.setState({ lastClosed, runs: ran([], `onLoad ${JSON.stringify(options)}`) });
|
|
18
18
|
},
|
|
19
|
-
// Runs each time the page comes into view: after onLoad,
|
|
19
|
+
// Runs each time the page comes into view: after onLoad, when a page above it closes, and when
|
|
20
|
+
// the dot comes back from the background.
|
|
20
21
|
onShow() {
|
|
21
22
|
this.setState((current) => ({ runs: ran(current.runs, 'onShow') }));
|
|
22
23
|
},
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<Text>{{ run.id }}. {{ run.hook }}</Text>
|
|
10
10
|
</For>
|
|
11
11
|
</View>
|
|
12
|
-
<Text variant="caption" tone="muted">Open another page, then come back
|
|
12
|
+
<Text variant="caption" tone="muted">Open another page, then come back. This page runs onHide, then onShow.</Text>
|
|
13
13
|
<Button variant="secondary" onClick="openAnother">Open another page</Button>
|
|
14
14
|
</View>
|
|
15
15
|
|
|
@@ -32,6 +32,6 @@
|
|
|
32
32
|
|
|
33
33
|
<View gap="small">
|
|
34
34
|
<Text variant="subtitle">The dot's hooks</Text>
|
|
35
|
-
<Text variant="caption" tone="muted">dot.ts can have hooks too
|
|
35
|
+
<Text variant="caption" tone="muted">dot.ts can have hooks too. onLaunch runs once when the dot starts. onError gets any error a page doesn't catch.</Text>
|
|
36
36
|
</View>
|
|
37
37
|
</View>
|
|
@@ -11,6 +11,7 @@ export default definePage({
|
|
|
11
11
|
this.setState({ depth, from, trail: `${from} › ${depth}`, options: JSON.stringify(options) });
|
|
12
12
|
},
|
|
13
13
|
},
|
|
14
|
+
// Only actions have this.navigation, so only they open and close pages.
|
|
14
15
|
actions: {
|
|
15
16
|
openAnother(state) {
|
|
16
17
|
this.navigation.push('basics/navigation', { depth: String(state.depth), trail: state.trail });
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
<View gap="small">
|
|
24
24
|
<Text variant="subtitle">back</Text>
|
|
25
|
-
<Text variant="caption" tone="muted">Closes this page, or as many as you ask.
|
|
25
|
+
<Text variant="caption" tone="muted">Closes this page, or as many as you ask. It never closes the first page. To close the dot, call this.dash.dot.close().</Text>
|
|
26
26
|
<View direction="row" gap="small">
|
|
27
27
|
<Button variant="secondary" onClick="back">Back</Button>
|
|
28
28
|
<Button variant="secondary" onClick="backTwo" disabled="{{ depth < 3 }}">Back two</Button>
|
|
@@ -5,9 +5,9 @@ export default definePage({
|
|
|
5
5
|
initialState: state,
|
|
6
6
|
configs: {
|
|
7
7
|
navigationBar: { title: 'Choose a genre' },
|
|
8
|
-
// This page's own background
|
|
9
|
-
// paints it behind the page, makes the list's cards to match, and picks text and bar
|
|
10
|
-
// that read on it. Going back shows the page below in its own colours again.
|
|
8
|
+
// This page's own background, a warm Salone sunset in light mode and the evening after it in
|
|
9
|
+
// dark. Dash paints it behind the page, makes the list's cards to match, and picks text and bar
|
|
10
|
+
// colours that read on it. Going back shows the page below in its own colours again.
|
|
11
11
|
colors: { background: { light: '#FFF3E0', dark: '#2B1A0E' } },
|
|
12
12
|
},
|
|
13
13
|
actions: {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<View>
|
|
2
2
|
<Text variant="title">Share links</Text>
|
|
3
|
-
<Text>Dash's •••
|
|
3
|
+
<Text>Dash's menu, ••• (⋮ on Android), has Share. It shares a link to the dot, which opens its first page. A page can let the link open it instead, with some of its options.</Text>
|
|
4
4
|
|
|
5
5
|
<View gap="small">
|
|
6
6
|
<Text variant="subtitle">definePage({ share })</Text>
|
|
7
|
-
<Text variant="caption" tone="muted">share: { options: ['concert'] } lets the link open the page with its concert option. Options not on the list stay out of the link, so nothing private goes in it. Write share out in place
|
|
7
|
+
<Text variant="caption" tone="muted">share: { options: ['concert'] } lets the link open the page with its concert option. Options not on the list stay out of the link, so nothing private goes in it. Write share out in place, as the build reads it without running the code.</Text>
|
|
8
8
|
<Text variant="caption" tone="muted">Open a concert, then tap ••• and Share.</Text>
|
|
9
9
|
<List>
|
|
10
10
|
<For each="{{ concerts }}" item="concert" key="id">
|
|
@@ -2,21 +2,30 @@ import state from './state';
|
|
|
2
2
|
|
|
3
3
|
export default definePage({
|
|
4
4
|
initialState: state,
|
|
5
|
+
// What Dash's bars show on this page. The Bars page has more.
|
|
5
6
|
configs: { navigationBar: { title: 'State' } },
|
|
7
|
+
// A mutation gets the state and returns only the fields that change. It can't wait, so it can't
|
|
8
|
+
// call Dash.
|
|
6
9
|
mutations: {
|
|
7
10
|
increment: (state) => {
|
|
8
11
|
const count = state.count + 1;
|
|
12
|
+
// State is read-only, so make a new list rather than change the old one.
|
|
9
13
|
return { count, taps: [{ id: count }, ...state.taps] };
|
|
10
14
|
},
|
|
11
15
|
reset: () => ({ count: 0, taps: [] }),
|
|
12
16
|
},
|
|
17
|
+
// An action can wait, call Dash, open pages and run other handlers. It changes the state with
|
|
18
|
+
// this.setState or a mutation.
|
|
13
19
|
actions: {
|
|
14
20
|
fillUp() {
|
|
21
|
+
// this.state is the latest state. The state an action gets is from when it started, so it
|
|
22
|
+
// wouldn't see the cheers this loop adds.
|
|
15
23
|
while (this.state.count < this.state.limit) {
|
|
16
24
|
this.mutations.increment();
|
|
17
25
|
}
|
|
18
26
|
},
|
|
19
27
|
undo() {
|
|
28
|
+
// setState takes the fields to change, or a function that gets the latest state.
|
|
20
29
|
this.setState((current) => ({ count: current.count - 1, taps: current.taps.slice(1) }));
|
|
21
30
|
},
|
|
22
31
|
},
|
|
@@ -2,9 +2,12 @@ export interface Tap {
|
|
|
2
2
|
id: number;
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
+
// State is plain data, as in JSON: text, numbers, true and false, null, lists and objects. Each
|
|
6
|
+
// open copy of the page gets its own. For "no value", use null, as setState skips undefined fields.
|
|
5
7
|
export default {
|
|
6
8
|
title: 'cheers for an encore',
|
|
7
9
|
count: 0,
|
|
8
10
|
limit: 5,
|
|
11
|
+
// `as Tap[]` tells TypeScript what the empty list will hold.
|
|
9
12
|
taps: [] as Tap[],
|
|
10
13
|
};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
<View gap="small">
|
|
6
6
|
<Text variant="subtitle">autoplay, loop and effect</Text>
|
|
7
|
-
<Text variant="caption" tone="muted">Gen Z artists.
|
|
7
|
+
<Text variant="caption" tone="muted">Gen Z artists. autoplay moves the slides every interval, here 3000 milliseconds, and pauses while you touch them. loop goes on from the last slide to the first. effect="scale" shrinks the slides beside the one in view.</Text>
|
|
8
8
|
<Carousel autoplay loop interval="3000" gap="medium" effect="scale" indicator="dots">
|
|
9
9
|
<For each="{{ artists }}" item="artist" key="id">
|
|
10
10
|
<View variant="card" align="center" gap="medium">
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
<View gap="small">
|
|
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.
|
|
26
|
+
<Text variant="caption" tone="muted">How Salone music grew, from palm-wine to Gen Z. index sets the slide. When you swipe, onChange sends the new slide's index. The buttons move the slides here, so indicator="none" hides the dots.</Text>
|
|
27
27
|
<Carousel index="{{ chapter }}" indicator="none" effect="slide" gap="small" padding="small" onChange="showChapter">
|
|
28
28
|
<For each="{{ chapters }}" item="card" key="title">
|
|
29
29
|
<View variant="card" align="center" gap="medium">
|
|
@@ -8,7 +8,8 @@ export default definePage({
|
|
|
8
8
|
restart: () => ({ progress: 0 }),
|
|
9
9
|
toggleBusy: (state) => ({ busy: !state.busy }),
|
|
10
10
|
toggleLoaded: (state) => ({ loaded: !state.loaded }),
|
|
11
|
-
// A
|
|
11
|
+
// A button's data-duration, in milliseconds, is how long its Toast stays. Without one, the
|
|
12
|
+
// Toast stays for its default time.
|
|
12
13
|
showToast: (
|
|
13
14
|
_state,
|
|
14
15
|
event: DataEvent<{ message: string; tone: string; duration?: string }>,
|
|
@@ -6,9 +6,9 @@ export interface PaymentStep {
|
|
|
6
6
|
status: StepStatus;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
// Sending
|
|
9
|
+
// Sending SLE 500 to Fatmata Conteh in Bo.
|
|
10
10
|
const PAYMENT = [
|
|
11
|
-
{ title: 'Paid', text: '
|
|
11
|
+
{ title: 'Paid', text: 'SLE 500 from your wallet' },
|
|
12
12
|
{ title: 'Sent', text: 'On its way to Bo' },
|
|
13
13
|
{ title: 'Received', text: 'By Fatmata Conteh' },
|
|
14
14
|
];
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
<View gap="small">
|
|
16
16
|
<Text variant="subtitle">Skeleton</Text>
|
|
17
|
-
<Text variant="caption" tone="muted">Shows the shape of what
|
|
17
|
+
<Text variant="caption" tone="muted">Shows the shape of what's loading, as lines of text, a circle or a box.</Text>
|
|
18
18
|
<View variant="card">
|
|
19
19
|
<If condition="{{ loaded }}">
|
|
20
20
|
<View direction="row" align="center" gap="large">
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
<Text variant="subtitle">A busy Button</Text>
|
|
66
66
|
<Text variant="caption" tone="muted">loading shows a spinner, and the button ignores taps.</Text>
|
|
67
67
|
<View variant="card">
|
|
68
|
-
<Button loading="{{ busy }}">{{ busy ? 'Paying…' : 'Pay
|
|
68
|
+
<Button loading="{{ busy }}">{{ busy ? 'Paying…' : 'Pay SLE 300 for two tickets' }}</Button>
|
|
69
69
|
<Switch label="Busy" checked="{{ busy }}" onChange="toggleBusy" />
|
|
70
70
|
</View>
|
|
71
71
|
</View>
|
|
@@ -3,10 +3,10 @@ import { errorMessage } from '@monimesl/dot-runtime';
|
|
|
3
3
|
import type { TicketType } from './state';
|
|
4
4
|
import state, { SHOWS, TICKETS } from './state';
|
|
5
5
|
|
|
6
|
-
// 2 tickets of
|
|
6
|
+
// 2 tickets of an SLE 1,200 type -> "SLE 2,400"
|
|
7
7
|
function total(tickets: number, ticket: TicketType): string {
|
|
8
8
|
const leones = tickets * TICKETS[ticket].price;
|
|
9
|
-
return `
|
|
9
|
+
return `SLE ${leones.toLocaleString('en-US')}`;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export default definePage({
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
<View gap="small">
|
|
17
17
|
<Text variant="subtitle">Input</Text>
|
|
18
|
-
<Text variant="caption" tone="muted">type sets the keyboard
|
|
18
|
+
<Text variant="caption" tone="muted">type sets the keyboard, such as email, phone, number or password. prefix and suffix sit inside the field. error shows under it, in place of hint. onSubmit comes when the person presses return, here in the promo code.</Text>
|
|
19
19
|
<View variant="card">
|
|
20
20
|
<Input label="Name" placeholder="Mariama Kamara" value="{{ name }}" maxLength="40" onChange="setName" />
|
|
21
21
|
<Input label="Email" type="email" placeholder="mariama@example.com" hint="{{ eTickets ? 'For the e-tickets' : 'Turn on e-tickets below to use it' }}" value="{{ email }}" disabled="{{ !eTickets }}" onChange="setEmail" />
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
<Text variant="caption" tone="muted">One choice from a few. A Radio, or the whole group, can be disabled.</Text>
|
|
38
38
|
<View variant="card">
|
|
39
39
|
<RadioGroup label="Ticket" value="{{ ticket }}" disabled="{{ sending }}" onChange="setTicket">
|
|
40
|
-
<Radio value="regular" label="Regular ·
|
|
41
|
-
<Radio value="vip" label="VIP, near the stage ·
|
|
42
|
-
<Radio value="table" label="Table for four ·
|
|
40
|
+
<Radio value="regular" label="Regular · SLE 150" />
|
|
41
|
+
<Radio value="vip" label="VIP, near the stage · SLE 400" />
|
|
42
|
+
<Radio value="table" label="Table for four · SLE 1,200" />
|
|
43
43
|
<Radio value="backstage" label="Backstage · sold out" disabled />
|
|
44
44
|
</RadioGroup>
|
|
45
45
|
</View>
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
<Notice tone="danger" title="Not booked">{{ failure }}</Notice>
|
|
91
91
|
</If>
|
|
92
92
|
|
|
93
|
-
<Text variant="caption" tone="muted">A Footer keeps its buttons at the bottom of the screen.</Text>
|
|
93
|
+
<Text variant="caption" tone="muted">A Footer keeps its buttons at the bottom of the screen. Put it last in the page's View.</Text>
|
|
94
94
|
<Footer>
|
|
95
95
|
<Button onClick="send" loading="{{ sending }}" disabled="{{ !agreed }}">Buy tickets</Button>
|
|
96
96
|
</Footer>
|
|
@@ -2,7 +2,7 @@ import { errorMessage } from '@monimesl/dot-runtime';
|
|
|
2
2
|
|
|
3
3
|
import state from './state';
|
|
4
4
|
|
|
5
|
-
// AUDACITY's id in Apple's catalog
|
|
5
|
+
// AUDACITY's id in Apple's catalog. Its cover's address can change, so the page looks it up.
|
|
6
6
|
const AUDACITY = 6811765244;
|
|
7
7
|
|
|
8
8
|
interface Lookup {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
size: 64,
|
|
3
3
|
loaded: '',
|
|
4
|
-
//
|
|
4
|
+
// Kept in state, not written in the view, so the build doesn't check that the file exists.
|
|
5
5
|
missing: 'statics/missing.png',
|
|
6
6
|
failure: '',
|
|
7
7
|
// The cover of Drizilik's album AUDACITY, which the page asks Apple's catalog for.
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
<View gap="small">
|
|
16
16
|
<Text variant="subtitle">From the web</Text>
|
|
17
|
-
<Text variant="caption" tone="muted">The cover of Drizilik's album AUDACITY. With aspect="1:1" and no width, it fills the card.</Text>
|
|
17
|
+
<Text variant="caption" tone="muted">The cover of Drizilik's album AUDACITY. A web picture loads only from a host in dot.json's network.hosts. With aspect="1:1" and no width, it fills the card.</Text>
|
|
18
18
|
<View variant="card" gap="small">
|
|
19
19
|
<If condition="{{ cover }}">
|
|
20
20
|
<Image src="{{ cover }}" alt="The cover of AUDACITY, by Drizilik" aspect="1:1" />
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
|
|
33
33
|
<View gap="small">
|
|
34
34
|
<Text variant="subtitle">shape and fit</Text>
|
|
35
|
-
<Text variant="caption" tone="muted">
|
|
35
|
+
<Text variant="caption" tone="muted">shape is rounded, square or circle. fit="cover", the default, fills the box and crops. fit="contain" shows the whole picture.</Text>
|
|
36
36
|
<View variant="card" direction="row" align="center" gap="large">
|
|
37
37
|
<Image src="statics/logo.png" alt="Rounded" width="56" height="56" shape="rounded" />
|
|
38
38
|
<Image src="statics/logo.png" alt="Square" width="56" height="56" shape="square" />
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
|
|
45
45
|
<View gap="small">
|
|
46
46
|
<Text variant="subtitle">onLoad</Text>
|
|
47
|
-
<Text variant="caption" tone="muted">
|
|
47
|
+
<Text variant="caption" tone="muted">Comes once the picture loads, with its own size in event.detail.width and height. The size on screen comes from state here.</Text>
|
|
48
48
|
<View variant="card" gap="small">
|
|
49
49
|
<Image src="statics/logo.png" alt="Logo" width="{{ size }}" height="{{ size }}" onLoad="logoLoaded" />
|
|
50
50
|
<Text>{{ size }} × {{ size }} on screen, {{ loaded }} in the file</Text>
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
|
|
58
58
|
<View gap="small">
|
|
59
59
|
<Text variant="subtitle">onError</Text>
|
|
60
|
-
<Text variant="caption" tone="muted">
|
|
60
|
+
<Text variant="caption" tone="muted">Comes when a picture fails to load. event.detail.message says which one.</Text>
|
|
61
61
|
<View variant="card">
|
|
62
62
|
<If condition="{{ failure }}">
|
|
63
63
|
<Text>{{ failure }}</Text>
|
|
@@ -14,7 +14,8 @@ export default definePage({
|
|
|
14
14
|
initialState: state,
|
|
15
15
|
configs: { navigationBar: { title: 'Layout' } },
|
|
16
16
|
hooks: {
|
|
17
|
-
// The shelf's covers come from Apple's catalog.
|
|
17
|
+
// The shelf's covers come from Apple's catalog. Dash sends requests only to the hosts in
|
|
18
|
+
// dot.json's network.hosts. The Network page shows more.
|
|
18
19
|
async onLoad() {
|
|
19
20
|
const ids = this.state.releases.map((release) => release.id).join(',');
|
|
20
21
|
try {
|
|
@@ -48,6 +49,7 @@ export default definePage({
|
|
|
48
49
|
openSection: (_state, event: DataEvent<{ name: string }>) => ({
|
|
49
50
|
section: event.data.name,
|
|
50
51
|
}),
|
|
52
|
+
// Scroll's change carries the index of the child at the start, once the row stops.
|
|
51
53
|
showFirst: (_state, event: IndexEvent) => ({ first: event.detail.index }),
|
|
52
54
|
shelfStart: () => ({ first: 0 }),
|
|
53
55
|
shelfEnd: (state) => ({ first: state.releases.length - 1 }),
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
<View gap="small">
|
|
6
6
|
<Text variant="subtitle">View</Text>
|
|
7
|
-
<Text variant="caption" tone="muted">A View puts its
|
|
7
|
+
<Text variant="caption" tone="muted">A View puts its children in a column, or in a row with direction="row". variant="card" gives it a card's look. Change the one below.</Text>
|
|
8
8
|
<View variant="card" direction="{{ direction }}" justify="{{ justify }}" align="{{ align }}" gap="{{ gap }}" wrap="{{ wrap }}">
|
|
9
9
|
<Button variant="secondary">Palm-wine</Button>
|
|
10
10
|
<Button variant="secondary">Gumbe</Button>
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
|
|
44
44
|
<View gap="small">
|
|
45
45
|
<Text variant="subtitle">grow and onTap</Text>
|
|
46
|
-
<Text variant="caption" tone="muted">grow
|
|
46
|
+
<Text variant="caption" tone="muted">grow makes a View fill the space left over. The song grows and the year doesn't. A View with onTap can be tapped, so tap the song.</Text>
|
|
47
47
|
<View direction="row" gap="small">
|
|
48
48
|
<View variant="card" grow onTap="playSong">
|
|
49
49
|
<Text>{{ playing ? 'Playing Exodus, by Drizilik' : 'Exodus, by Drizilik' }}</Text>
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
|
|
73
73
|
<View gap="small">
|
|
74
74
|
<Text variant="subtitle">Stack</Text>
|
|
75
|
-
<Text variant="caption" tone="muted">A Stack lays its children on top of each other, such as words over a picture.</Text>
|
|
75
|
+
<Text variant="caption" tone="muted">A Stack lays its children on top of each other, the first at the bottom, such as words over a picture.</Text>
|
|
76
76
|
<Stack radius="large" aspect="16:9">
|
|
77
77
|
<View background="gold" />
|
|
78
78
|
<View justify="end" padding="large">
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
|
|
90
90
|
<View gap="small">
|
|
91
91
|
<Text variant="subtitle">Scroll</Text>
|
|
92
|
-
<Text variant="caption" tone="muted">A Scroll moves a row sideways.
|
|
92
|
+
<Text variant="caption" tone="muted">A Scroll moves a row sideways. snap="start" stops it at the start of a release. Once it stops, onChange sends the index of the first release in view. Setting index scrolls there, as the buttons do.</Text>
|
|
93
93
|
<Scroll gap="medium" snap="start" index="{{ first }}" onChange="showFirst">
|
|
94
94
|
<For each="{{ releases }}" item="release" key="id">
|
|
95
95
|
<View gap="small">
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
|
|
114
114
|
<View gap="small">
|
|
115
115
|
<Text variant="subtitle">Grid</Text>
|
|
116
|
-
<Text variant="caption" tone="muted">A Grid keeps its columns the same width. A GridItem shows an icon or a picture, with a label.</Text>
|
|
116
|
+
<Text variant="caption" tone="muted">A Grid keeps its columns the same width, 4 unless columns says. A GridItem shows an icon or a picture, with a label and an optional badge.</Text>
|
|
117
117
|
<View variant="card" gap="medium">
|
|
118
118
|
<Grid columns="4" gap="small">
|
|
119
119
|
<GridItem icon="microphone" label="Artists" data-name="Artists" onTap="openSection" />
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<View>
|
|
2
2
|
<Text variant="title">Lists</Text>
|
|
3
|
-
<Text>A List shows rows in a card. A ListItem can show an icon or a picture, a subtitle, and a value or a badge at its end. A row
|
|
3
|
+
<Text>A List shows rows in a card. A ListItem can show an icon or a picture, a subtitle, and a value or a badge at its end. A row with onTap shows an arrow.</Text>
|
|
4
4
|
|
|
5
5
|
<View gap="small">
|
|
6
6
|
<Text variant="subtitle">List and ListItem</Text>
|
|
7
|
-
<Text variant="caption" tone="muted">
|
|
7
|
+
<Text variant="caption" tone="muted">Tap an artist. The row's data-id tells the page which one.</Text>
|
|
8
8
|
<List>
|
|
9
9
|
<For each="{{ artists }}" item="artist" key="id">
|
|
10
10
|
<ListItem icon="microphone" title="{{ artist.name }}" subtitle="{{ artist.song }}" value="{{ artist.genre }}" data-id="{{ artist.id }}" onTap="choose" />
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
</View>
|
|
17
17
|
|
|
18
18
|
<View gap="small">
|
|
19
|
-
<Text variant="subtitle">
|
|
20
|
-
<Text variant="caption" tone="muted">
|
|
19
|
+
<Text variant="subtitle">A picture and a badge</Text>
|
|
20
|
+
<Text variant="caption" tone="muted">A ListItem's children show at its end, in place of value. size="md" gives the rows more room and a bigger picture. Lists are size="sm" by default.</Text>
|
|
21
21
|
<List size="md">
|
|
22
22
|
<For each="{{ releases }}" item="release" key="id">
|
|
23
23
|
<ListItem image="statics/logo.png" title="{{ release.title }}" subtitle="{{ release.artist }} · {{ release.year }}">
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
<View gap="small">
|
|
31
31
|
<Text variant="subtitle">onEndReached</Text>
|
|
32
|
-
<Text variant="caption" tone="muted">Comes
|
|
32
|
+
<Text variant="caption" tone="muted">Comes as the last row nears the screen, so the page can add more. It comes again once there's a new last row. {{ chart.length }} of {{ chartSize }} songs so far.</Text>
|
|
33
33
|
<List onEndReached="showMore">
|
|
34
34
|
<For each="{{ chart }}" item="song" key="id">
|
|
35
35
|
<ListItem title="{{ song.id }}. {{ song.title }}" value="{{ song.plays }}" />
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
|
|
53
53
|
<View gap="small">
|
|
54
54
|
<Text variant="subtitle">Disclosure</Text>
|
|
55
|
-
<Text variant="caption" tone="muted">A row that opens to show more, such as an answer. The person opens and closes it, and open sets how it starts.</Text>
|
|
55
|
+
<Text variant="caption" tone="muted">A row that opens to show more, such as an answer. The person opens and closes it, and open sets how it starts. onToggle sends event.detail.open each time.</Text>
|
|
56
56
|
<View variant="card" gap="none">
|
|
57
57
|
<Disclosure title="Can I get a refund?" subtitle="Tickets and refunds" open>
|
|
58
58
|
<Text>Yes, until the Friday before the show. After that, you can give your ticket to someone else.</Text>
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
|
|
71
71
|
<View gap="small">
|
|
72
72
|
<Text variant="subtitle">EmptyState</Text>
|
|
73
|
-
<Text variant="caption" tone="muted">Shows
|
|
73
|
+
<Text variant="caption" tone="muted">Shows where a list has nothing yet. Its children, such as a button, show under its text.</Text>
|
|
74
74
|
<View variant="card">
|
|
75
75
|
<If condition="{{ saved.length > 0 }}">
|
|
76
76
|
<For each="{{ saved }}" item="title" key="*this">
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
<View gap="small">
|
|
6
6
|
<Text variant="subtitle">AmountInput</Text>
|
|
7
|
-
<Text variant="caption" tone="muted">Formats the amount as you type.
|
|
7
|
+
<Text variant="caption" tone="muted">Formats the amount as you type. onChange sends a number in cents, the minor unit, so 150 is SLE 1.50. An empty field sends null.</Text>
|
|
8
8
|
<AmountInput label="Tip for the band" placeholder="0.00" value="{{ amount }}" disabled="{{ locked }}" onChange="setAmount" hint="The QR code below asks for it" />
|
|
9
9
|
<Switch label="Lock the tip" checked="{{ locked }}" onChange="setLocked" />
|
|
10
10
|
</View>
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
<View gap="small">
|
|
33
33
|
<Text variant="subtitle">CodeInput</Text>
|
|
34
|
-
<Text variant="caption" tone="muted">A one-time code, one box per digit. Type it, paste it, or let the phone fill it from an SMS. onComplete comes when the last box fills.</Text>
|
|
34
|
+
<Text variant="caption" tone="muted">A one-time code, one box per digit. Type it, paste it, or let the phone fill it from an SMS. onComplete comes when the last box fills, with the code in event.detail.value.</Text>
|
|
35
35
|
<If condition="{{ verified }}">
|
|
36
36
|
<Notice tone="success" title="Code accepted">Your two tickets are confirmed.</Notice>
|
|
37
37
|
<Button variant="secondary" onClick="startAgain">Start again</Button>
|