fixing hitTest bounds for clickable. using Constructors for Clickable events. starting to think about design systems..

master
Dustin Swan 4 days ago
parent 5af3af6b6c
commit 86996ed4ef
Signed by: dustinswan
GPG Key ID: 30D46587E2100467

@ -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…
Cancel
Save