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 { runApp } from './runtime';
import { builtins } from './builtins'; import { builtins } from './builtins';
import counterApp from './counter.cg?raw';
import stdlibCode from './stdlib.cg?raw'; import stdlibCode from './stdlib.cg?raw';
import designTokensCode from './design-tokens.cg?raw';
import uiComponentsCode from './ui-components.cg?raw'; import uiComponentsCode from './ui-components.cg?raw';
import textInputCode from './textinput-test.cg?raw'; import textInputCode from './textinput-test.cg?raw';
import testCode from './test.cg?raw'; import testCode from './test.cg?raw';
import counterApp from './counter.cg?raw';
const canvas = document.createElement('canvas'); const canvas = document.createElement('canvas');
canvas.width = 800; canvas.width = 800;
canvas.height = 600; canvas.height = 600;
canvas.style.border = "1px solid #000";
document.body.appendChild(canvas); 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 tokens = tokenize(cgCode);
const parser = new Parser(tokens); const parser = new Parser(tokens);

@ -16,7 +16,7 @@ export function runApp(app: App, canvas: HTMLCanvasElement) {
if (app.view.kind !== 'closure') if (app.view.kind !== 'closure')
throw new Error('view must be a function'); throw new Error('view must be a function');
const viewport = { const viewport: Value = {
kind: 'record', kind: 'record',
fields: { fields: {
width: { kind: 'int', value: canvas.width }, width: { kind: 'int', value: canvas.width },
@ -61,13 +61,9 @@ export function runApp(app: App, canvas: HTMLCanvasElement) {
return; return;
} }
const eventName = hitTest(x, y);
if (eventName) { const event = hitTest(x, y);
const event: Value = { if (event) {
kind: 'constructor',
name: eventName,
args: []
}
handleEvent(event); handleEvent(event);
} }
}); });

@ -2,17 +2,22 @@ init = { text = "" };
update = state event \ event update = state event \ event
| UpdateText newText \ state.{ text = newText } | UpdateText newText \ state.{ text = newText }
| Submit _ \ state.{ text = "" }; | Submit _ \ state.{ text = "" }
# | _ \ state; | Go \ state.{ text = "" };
view = state viewport \ view = state viewport \
Column { Column {
gap = 20, gap = 20,
children = [ 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 }, Text { content = "You typed: " & state.text, x = 0, y = 20 },
Stack { Stack {
children = [ children = [
Rect { w = 300, h = 40, color = "white" }, Rect { w = viewport.width, h = 40, color = "blue" },
TextInput { TextInput {
value = state.text, value = state.text,
placeholder = "Type something...", placeholder = "Type something...",
@ -24,9 +29,9 @@ view = state viewport \
onInput = UpdateText, onInput = UpdateText,
onSubmit = Submit 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: 'text', content: string, x: number, y: number }
| { kind: 'row', children: UIValue[], gap: number } | { kind: 'row', children: UIValue[], gap: number }
| { kind: 'column', 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: 'padding', child: UIValue, amount: number }
| { kind: 'stack', children: UIValue[] } | { 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 } | { 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 \ button = config \
Clickable { Clickable {
event = config.event, event = config.event,
child = Stack { child = Stack {
children = [ children = [
Rect { w = 100, h = 40, color = "blue" }, Rect { w = 100, h = 40, color = config.theme.colors.primary },
Text { content = config.label, x = 10, y = 25} Text { content = config.label, x = 10, y = 25, color = config.theme.colors.bg }
] ]
} }
}; };

@ -5,7 +5,7 @@ type ClickRegion = {
y: number; y: number;
width: number; width: number;
height: number; height: number;
event: string; event: Value;
}; };
type TextInputRegion = { type TextInputRegion = {
@ -171,14 +171,12 @@ function measure(ui: UIValue): { width: number, height: number } {
case 'text-input': case 'text-input':
return { width: ui.w, height: ui.h }; 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) { for (const region of clickRegions) {
if (x >= region.x && x < region.x + region.width && 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; return region.event;
} }
} }

@ -57,10 +57,10 @@ export function valueToUI(value: Value): UIValue {
const child = fields.child; const child = fields.child;
const event = fields.event; const event = fields.event;
if (event.kind !== 'string') if (event.kind !== 'constructor')
throw new Error('Invalid Clickable fields'); 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': { case 'Padding': {

Loading…
Cancel
Save