fixing hitTest bounds for clickable. using Constructors for Clickable events. starting to think about design systems..
This commit is contained in:
parent
5af3af6b6c
commit
86996ed4ef
8 changed files with 67 additions and 26 deletions
38
src/design-tokens.cg
Normal file
38
src/design-tokens.cg
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
colors = {
|
||||
primary = "#0066cc",
|
||||
primaryDark = "#0052a3",
|
||||
danger = "#dc3545",
|
||||
success = "#28a745",
|
||||
bg = "#ffffff",
|
||||
bgGray = "#f8f9fa",
|
||||
text = "#212529",
|
||||
textLight = "#6c757d",
|
||||
border = "#dee2e6"
|
||||
};
|
||||
|
||||
spacing = {
|
||||
xs = 4,
|
||||
sm = 8,
|
||||
md = 16,
|
||||
lg = 32,
|
||||
xl = 64
|
||||
};
|
||||
|
||||
primaryStyle = {
|
||||
bg = colors.primary,
|
||||
fg = colors.bg,
|
||||
px = spacing.md,
|
||||
py = spacing.sm
|
||||
};
|
||||
|
||||
dangerStyle = {
|
||||
bg = colors.danger,
|
||||
fg = colors.bg,
|
||||
px = spacing.md,
|
||||
py = spacing.sm
|
||||
};
|
||||
|
||||
theme = {
|
||||
colors = colors,
|
||||
spacing = spacing
|
||||
};
|
||||
|
|
@ -5,18 +5,21 @@ import { Parser } from './parser'
|
|||
import { runApp } from './runtime';
|
||||
import { builtins } from './builtins';
|
||||
|
||||
import counterApp from './counter.cg?raw';
|
||||
import stdlibCode from './stdlib.cg?raw';
|
||||
import designTokensCode from './design-tokens.cg?raw';
|
||||
import uiComponentsCode from './ui-components.cg?raw';
|
||||
|
||||
import textInputCode from './textinput-test.cg?raw';
|
||||
import testCode from './test.cg?raw';
|
||||
import counterApp from './counter.cg?raw';
|
||||
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = 800;
|
||||
canvas.height = 600;
|
||||
canvas.style.border = "1px solid #000";
|
||||
document.body.appendChild(canvas);
|
||||
|
||||
const cgCode = stdlibCode + '\n' + uiComponentsCode + '\n' + textInputCode;
|
||||
const cgCode = stdlibCode + '\n' + designTokensCode + '\n' + uiComponentsCode + '\n' + textInputCode;
|
||||
|
||||
const tokens = tokenize(cgCode);
|
||||
const parser = new Parser(tokens);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export function runApp(app: App, canvas: HTMLCanvasElement) {
|
|||
if (app.view.kind !== 'closure')
|
||||
throw new Error('view must be a function');
|
||||
|
||||
const viewport = {
|
||||
const viewport: Value = {
|
||||
kind: 'record',
|
||||
fields: {
|
||||
width: { kind: 'int', value: canvas.width },
|
||||
|
|
@ -61,13 +61,9 @@ export function runApp(app: App, canvas: HTMLCanvasElement) {
|
|||
return;
|
||||
}
|
||||
|
||||
const eventName = hitTest(x, y);
|
||||
if (eventName) {
|
||||
const event: Value = {
|
||||
kind: 'constructor',
|
||||
name: eventName,
|
||||
args: []
|
||||
}
|
||||
|
||||
const event = hitTest(x, y);
|
||||
if (event) {
|
||||
handleEvent(event);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,17 +2,22 @@ init = { text = "" };
|
|||
|
||||
update = state event \ event
|
||||
| UpdateText newText \ state.{ text = newText }
|
||||
| Submit _ \ state.{ text = "" };
|
||||
# | _ \ state;
|
||||
| Submit _ \ state.{ text = "" }
|
||||
| Go \ state.{ text = "" };
|
||||
|
||||
view = state viewport \
|
||||
Column {
|
||||
gap = 20,
|
||||
children = [
|
||||
Text {
|
||||
content = "window: " & str(viewport.width) & " x " & str(viewport.height),
|
||||
x = 0,
|
||||
y = 20
|
||||
},
|
||||
Text { content = "You typed: " & state.text, x = 0, y = 20 },
|
||||
Stack {
|
||||
children = [
|
||||
Rect { w = 300, h = 40, color = "white" },
|
||||
Rect { w = viewport.width, h = 40, color = "blue" },
|
||||
TextInput {
|
||||
value = state.text,
|
||||
placeholder = "Type something...",
|
||||
|
|
@ -24,9 +29,9 @@ view = state viewport \
|
|||
onInput = UpdateText,
|
||||
onSubmit = Submit
|
||||
}
|
||||
# button ({ label = "Go", event = Go })
|
||||
]
|
||||
}
|
||||
},
|
||||
button { label = "Go", event = Go, theme = theme }
|
||||
]
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ export type UIValue =
|
|||
| { kind: 'text', content: string, x: number, y: number }
|
||||
| { kind: 'row', children: UIValue[], gap: number }
|
||||
| { kind: 'column', children: UIValue[], gap: number }
|
||||
| { kind: 'clickable', child: UIValue, event: string }
|
||||
| { kind: 'clickable', child: UIValue, event: Value }
|
||||
| { kind: 'padding', child: UIValue, amount: number }
|
||||
| { kind: 'stack', children: UIValue[] }
|
||||
| { kind: 'text-input', value: string, placeholder: string, x: number, y: number, w: number, h: number, focused: boolean, onInput: Value, onSubmit: Value }
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
# button : Record -> UI
|
||||
button = config \
|
||||
Clickable {
|
||||
event = config.event,
|
||||
child = Stack {
|
||||
children = [
|
||||
Rect { w = 100, h = 40, color = "blue" },
|
||||
Text { content = config.label, x = 10, y = 25}
|
||||
Rect { w = 100, h = 40, color = config.theme.colors.primary },
|
||||
Text { content = config.label, x = 10, y = 25, color = config.theme.colors.bg }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ type ClickRegion = {
|
|||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
event: string;
|
||||
event: Value;
|
||||
};
|
||||
|
||||
type TextInputRegion = {
|
||||
|
|
@ -171,14 +171,12 @@ function measure(ui: UIValue): { width: number, height: number } {
|
|||
case 'text-input':
|
||||
return { width: ui.w, height: ui.h };
|
||||
}
|
||||
|
||||
// return { width: 0, height: 0 };
|
||||
}
|
||||
|
||||
export function hitTest(x: number, y: number): string | null {
|
||||
export function hitTest(x: number, y: number): Value | null {
|
||||
for (const region of clickRegions) {
|
||||
if (x >= region.x && x < region.x + region.width &&
|
||||
x >= region.y && y < region.y + region.height) {
|
||||
y >= region.y && y < region.y + region.height) {
|
||||
return region.event;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,10 +57,10 @@ export function valueToUI(value: Value): UIValue {
|
|||
const child = fields.child;
|
||||
const event = fields.event;
|
||||
|
||||
if (event.kind !== 'string')
|
||||
throw new Error('Invalid Clickable fields');
|
||||
if (event.kind !== 'constructor')
|
||||
throw new Error('Clickable event must be a constructor');
|
||||
|
||||
return { kind: 'clickable', event: event.value, child: valueToUI(child) };
|
||||
return { kind: 'clickable', event: event, child: valueToUI(child) };
|
||||
}
|
||||
|
||||
case 'Padding': {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue