kumiki 0.1.1

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.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +256 -0
  4. data/lib/kumiki/animation/animated_state.rb +83 -0
  5. data/lib/kumiki/animation/easing.rb +62 -0
  6. data/lib/kumiki/animation/value_tween.rb +69 -0
  7. data/lib/kumiki/app.rb +381 -0
  8. data/lib/kumiki/box.rb +40 -0
  9. data/lib/kumiki/chart/area_chart.rb +308 -0
  10. data/lib/kumiki/chart/bar_chart.rb +291 -0
  11. data/lib/kumiki/chart/base_chart.rb +213 -0
  12. data/lib/kumiki/chart/chart_helpers.rb +74 -0
  13. data/lib/kumiki/chart/gauge_chart.rb +174 -0
  14. data/lib/kumiki/chart/heatmap_chart.rb +223 -0
  15. data/lib/kumiki/chart/line_chart.rb +292 -0
  16. data/lib/kumiki/chart/pie_chart.rb +222 -0
  17. data/lib/kumiki/chart/scales.rb +79 -0
  18. data/lib/kumiki/chart/scatter_chart.rb +306 -0
  19. data/lib/kumiki/chart/stacked_bar_chart.rb +279 -0
  20. data/lib/kumiki/column.rb +351 -0
  21. data/lib/kumiki/core.rb +2511 -0
  22. data/lib/kumiki/dsl.rb +408 -0
  23. data/lib/kumiki/frame_ranma.rb +570 -0
  24. data/lib/kumiki/markdown/ast.rb +127 -0
  25. data/lib/kumiki/markdown/mermaid/layout.rb +389 -0
  26. data/lib/kumiki/markdown/mermaid/models.rb +235 -0
  27. data/lib/kumiki/markdown/mermaid/parser.rb +522 -0
  28. data/lib/kumiki/markdown/mermaid/renderer.rb +339 -0
  29. data/lib/kumiki/markdown/parser.rb +808 -0
  30. data/lib/kumiki/markdown/renderer.rb +642 -0
  31. data/lib/kumiki/markdown/theme.rb +168 -0
  32. data/lib/kumiki/render_node.rb +262 -0
  33. data/lib/kumiki/row.rb +288 -0
  34. data/lib/kumiki/spacer.rb +20 -0
  35. data/lib/kumiki/style.rb +799 -0
  36. data/lib/kumiki/theme.rb +567 -0
  37. data/lib/kumiki/themes/material.rb +40 -0
  38. data/lib/kumiki/themes/tokyo_night.rb +11 -0
  39. data/lib/kumiki/version.rb +5 -0
  40. data/lib/kumiki/widgets/button.rb +105 -0
  41. data/lib/kumiki/widgets/calendar.rb +1028 -0
  42. data/lib/kumiki/widgets/checkbox.rb +119 -0
  43. data/lib/kumiki/widgets/container.rb +111 -0
  44. data/lib/kumiki/widgets/data_table.rb +670 -0
  45. data/lib/kumiki/widgets/divider.rb +31 -0
  46. data/lib/kumiki/widgets/image.rb +105 -0
  47. data/lib/kumiki/widgets/input.rb +485 -0
  48. data/lib/kumiki/widgets/markdown.rb +58 -0
  49. data/lib/kumiki/widgets/modal.rb +165 -0
  50. data/lib/kumiki/widgets/multiline_input.rb +970 -0
  51. data/lib/kumiki/widgets/multiline_text.rb +180 -0
  52. data/lib/kumiki/widgets/net_image.rb +100 -0
  53. data/lib/kumiki/widgets/progress_bar.rb +72 -0
  54. data/lib/kumiki/widgets/radio_buttons.rb +93 -0
  55. data/lib/kumiki/widgets/slider.rb +135 -0
  56. data/lib/kumiki/widgets/switch.rb +84 -0
  57. data/lib/kumiki/widgets/tabs.rb +175 -0
  58. data/lib/kumiki/widgets/text.rb +120 -0
  59. data/lib/kumiki/widgets/tree.rb +434 -0
  60. data/lib/kumiki/widgets/webview.rb +87 -0
  61. data/lib/kumiki.rb +130 -0
  62. metadata +113 -0
data/lib/kumiki/dsl.rb ADDED
@@ -0,0 +1,408 @@
1
+ # DSL - Block-based UI tree builder (CSS-inspired)
2
+ #
3
+ # Uses a widget stack to manage implicit parent-child relationships.
4
+ # All DSL functions are methods of the Kumiki::DSL module.
5
+ # Include Kumiki (or Kumiki::DSL) to use them.
6
+ #
7
+ # Usage:
8
+ # include Kumiki
9
+ #
10
+ # column(padding: 16.0) {
11
+ # text "Count: #{@count}", font_size: 32.0, color: 0xFFC0CAF5
12
+ # row(spacing: 8.0) {
13
+ # button(" - ", width: 80.0) { @count -= 1 }
14
+ # spacer
15
+ # button(" + ", width: 80.0) { @count += 1 }
16
+ # }
17
+ # }
18
+
19
+ module Kumiki
20
+ module DSL
21
+ # Widget stack for tracking current parent container
22
+ STACK = []
23
+
24
+ private
25
+
26
+ def __dsl_push(w)
27
+ STACK.push(w)
28
+ end
29
+
30
+ def __dsl_pop
31
+ STACK.pop
32
+ end
33
+
34
+ def __dsl_auto_add(w)
35
+ len = STACK.length
36
+ if len > 0
37
+ parent = STACK.last
38
+ if parent != nil
39
+ parent.add(w)
40
+ end
41
+ end
42
+ end
43
+
44
+ # Applies keyword arguments directly to a widget.
45
+ def __apply_kwargs(widget, kwargs, typography)
46
+ # Layout
47
+ widget.fixed_width(kwargs[:width]) if kwargs.key?(:width)
48
+ widget.fixed_height(kwargs[:height]) if kwargs.key?(:height)
49
+ if kwargs.key?(:padding)
50
+ p = kwargs[:padding]
51
+ widget.padding(p, p, p, p)
52
+ end
53
+ widget.flex(kwargs[:flex]) if kwargs.key?(:flex)
54
+ widget.fit_content if kwargs[:fit_content]
55
+ # Container
56
+ widget.spacing(kwargs[:spacing]) if kwargs.key?(:spacing)
57
+ widget.scrollable if kwargs[:scrollable]
58
+ widget.pin_to_bottom if kwargs[:pin_to_bottom]
59
+ widget.pin_to_end if kwargs[:pin_to_end]
60
+ # Visual
61
+ widget.bg_color(kwargs[:bg_color]) if kwargs.key?(:bg_color)
62
+ widget.border_color(kwargs[:border_color]) if kwargs.key?(:border_color)
63
+ widget.border_radius(kwargs[:border_radius]) if kwargs.key?(:border_radius)
64
+ # Expanding
65
+ if kwargs[:expanding]
66
+ widget.set_width_policy(Kumiki::EXPANDING)
67
+ widget.set_height_policy(Kumiki::EXPANDING)
68
+ end
69
+ widget.set_width_policy(Kumiki::EXPANDING) if kwargs[:expanding_width]
70
+ widget.set_height_policy(Kumiki::EXPANDING) if kwargs[:expanding_height]
71
+ # Typography (text/button/checkbox etc.)
72
+ if typography
73
+ widget.font_size(kwargs[:font_size]) if kwargs.key?(:font_size)
74
+ widget.color(kwargs[:color]) if kwargs.key?(:color)
75
+ widget.text_color(kwargs[:text_color]) if kwargs.key?(:text_color)
76
+ widget.bold if kwargs[:bold]
77
+ widget.italic if kwargs[:italic]
78
+ widget.font_family(kwargs[:font_family]) if kwargs.key?(:font_family)
79
+ widget.kind(kwargs[:kind]) if kwargs.key?(:kind)
80
+ if kwargs.key?(:align)
81
+ a = kwargs[:align]
82
+ if a == :center
83
+ widget.align(1)
84
+ elsif a == :right
85
+ widget.align(2)
86
+ elsif a == :left
87
+ widget.align(0)
88
+ else
89
+ widget.align(a)
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ public
96
+
97
+ # --- Style helper ---
98
+
99
+ def s
100
+ Kumiki::Style.new
101
+ end
102
+
103
+ # --- Container DSL functions ---
104
+
105
+ def column(base_style = nil, **kwargs, &block)
106
+ col = Kumiki::Column.new
107
+ if base_style != nil
108
+ base_style.apply(col)
109
+ end
110
+ __apply_kwargs(col, kwargs, false) if kwargs.length > 0
111
+ __dsl_push(col)
112
+ yield
113
+ __dsl_pop
114
+ __dsl_auto_add(col)
115
+ col
116
+ end
117
+
118
+ def row(base_style = nil, **kwargs, &block)
119
+ r = Kumiki::Row.new
120
+ if base_style != nil
121
+ base_style.apply(r)
122
+ end
123
+ __apply_kwargs(r, kwargs, false) if kwargs.length > 0
124
+ __dsl_push(r)
125
+ yield
126
+ __dsl_pop
127
+ __dsl_auto_add(r)
128
+ r
129
+ end
130
+
131
+ def box(base_style = nil, **kwargs, &block)
132
+ b = Kumiki::Box.new
133
+ if base_style != nil
134
+ base_style.apply(b)
135
+ end
136
+ __apply_kwargs(b, kwargs, false) if kwargs.length > 0
137
+ __dsl_push(b)
138
+ yield
139
+ __dsl_pop
140
+ __dsl_auto_add(b)
141
+ b
142
+ end
143
+
144
+ def container(base_style = nil, **kwargs, &block)
145
+ c = Kumiki::Container.new(nil)
146
+ if base_style != nil
147
+ base_style.apply_layout(c)
148
+ base_style.apply_visual(c)
149
+ end
150
+ __apply_kwargs(c, kwargs, false) if kwargs.length > 0
151
+ __dsl_push(c)
152
+ yield
153
+ __dsl_pop
154
+ __dsl_auto_add(c)
155
+ c
156
+ end
157
+
158
+ # --- Leaf DSL functions ---
159
+
160
+ def text(content, base_style = nil, **kwargs)
161
+ w = Kumiki::Text.new(content)
162
+ if base_style != nil
163
+ base_style.apply(w)
164
+ base_style.apply_typography(w)
165
+ end
166
+ __apply_kwargs(w, kwargs, true) if kwargs.length > 0
167
+ __dsl_auto_add(w)
168
+ w
169
+ end
170
+
171
+ def button(label, base_style = nil, **kwargs, &block)
172
+ w = Kumiki::Button.new(label)
173
+ if base_style != nil
174
+ base_style.apply(w)
175
+ base_style.apply_typography(w)
176
+ end
177
+ __apply_kwargs(w, kwargs, true) if kwargs.length > 0
178
+ if block_given?
179
+ w.on_click { yield }
180
+ end
181
+ __dsl_auto_add(w)
182
+ w
183
+ end
184
+
185
+ def spacer
186
+ w = Kumiki::Spacer.new
187
+ __dsl_auto_add(w)
188
+ w
189
+ end
190
+
191
+ def divider
192
+ w = Kumiki::Divider.new
193
+ __dsl_auto_add(w)
194
+ w
195
+ end
196
+
197
+ def checkbox(label, base_style = nil, **kwargs)
198
+ w = Kumiki::Checkbox.new(label)
199
+ if base_style != nil
200
+ base_style.apply(w)
201
+ base_style.apply_typography(w)
202
+ end
203
+ __apply_kwargs(w, kwargs, true) if kwargs.length > 0
204
+ __dsl_auto_add(w)
205
+ w
206
+ end
207
+
208
+ def radio_buttons(options, base_style = nil, **kwargs)
209
+ w = Kumiki::RadioButtons.new(options)
210
+ if base_style != nil
211
+ base_style.apply(w)
212
+ end
213
+ __apply_kwargs(w, kwargs, false) if kwargs.length > 0
214
+ __dsl_auto_add(w)
215
+ w
216
+ end
217
+
218
+ def slider(min_val, max_val, base_style = nil, **kwargs)
219
+ w = Kumiki::Slider.new(min_val, max_val)
220
+ if base_style != nil
221
+ base_style.apply(w)
222
+ end
223
+ __apply_kwargs(w, kwargs, false) if kwargs.length > 0
224
+ __dsl_auto_add(w)
225
+ w
226
+ end
227
+
228
+ def image(path, base_style = nil, **kwargs)
229
+ w = Kumiki::ImageWidget.new(path)
230
+ if base_style != nil
231
+ base_style.apply(w)
232
+ end
233
+ __apply_kwargs(w, kwargs, false) if kwargs.length > 0
234
+ __dsl_auto_add(w)
235
+ w
236
+ end
237
+
238
+ def net_image(url, base_style = nil, **kwargs)
239
+ w = Kumiki::NetImageWidget.new(url)
240
+ if base_style != nil
241
+ base_style.apply(w)
242
+ end
243
+ __apply_kwargs(w, kwargs, false) if kwargs.length > 0
244
+ __dsl_auto_add(w)
245
+ w
246
+ end
247
+
248
+ def multiline_text(content, base_style = nil, **kwargs)
249
+ w = Kumiki::MultilineText.new(content)
250
+ if base_style != nil
251
+ base_style.apply(w)
252
+ base_style.apply_typography(w)
253
+ end
254
+ __apply_kwargs(w, kwargs, true) if kwargs.length > 0
255
+ __dsl_auto_add(w)
256
+ w
257
+ end
258
+
259
+ def markdown_text(content, base_style = nil, **kwargs)
260
+ w = Kumiki::Markdown.new(content)
261
+ if base_style != nil
262
+ base_style.apply(w)
263
+ end
264
+ __apply_kwargs(w, kwargs, false) if kwargs.length > 0
265
+ __dsl_auto_add(w)
266
+ w
267
+ end
268
+
269
+ def text_input(state, base_style = nil, **kwargs)
270
+ w = Kumiki::Input.new(state)
271
+ if base_style != nil
272
+ base_style.apply(w)
273
+ base_style.apply_typography(w)
274
+ end
275
+ __apply_kwargs(w, kwargs, true) if kwargs.length > 0
276
+ __dsl_auto_add(w)
277
+ w
278
+ end
279
+
280
+ def multiline_input(state, base_style = nil, **kwargs)
281
+ w = Kumiki::MultilineInput.new(state)
282
+ if base_style != nil
283
+ base_style.apply(w)
284
+ end
285
+ __apply_kwargs(w, kwargs, false) if kwargs.length > 0
286
+ __dsl_auto_add(w)
287
+ w
288
+ end
289
+
290
+ def data_table(cols, widths, rows, base_style = nil, **kwargs)
291
+ w = Kumiki::DataTable.new(cols, widths, rows)
292
+ if base_style != nil
293
+ base_style.apply(w)
294
+ base_style.apply_typography(w)
295
+ end
296
+ __apply_kwargs(w, kwargs, true) if kwargs.length > 0
297
+ __dsl_auto_add(w)
298
+ w
299
+ end
300
+
301
+ def switch_toggle
302
+ w = Kumiki::Switch.new
303
+ __dsl_auto_add(w)
304
+ w
305
+ end
306
+
307
+ def progress_bar
308
+ w = Kumiki::ProgressBar.new
309
+ __dsl_auto_add(w)
310
+ w
311
+ end
312
+
313
+ # --- Complex widget DSL functions ---
314
+
315
+ def tabs(labels, contents)
316
+ w = Kumiki::Tabs.new(labels, contents)
317
+ __dsl_auto_add(w)
318
+ w
319
+ end
320
+
321
+ def tree(state)
322
+ w = Kumiki::Tree.new(state)
323
+ __dsl_auto_add(w)
324
+ w
325
+ end
326
+
327
+ def calendar(state)
328
+ w = Kumiki::Calendar.new(state)
329
+ __dsl_auto_add(w)
330
+ w
331
+ end
332
+
333
+ def modal(body)
334
+ w = Kumiki::Modal.new(body)
335
+ __dsl_auto_add(w)
336
+ w
337
+ end
338
+
339
+ # --- Chart DSL functions ---
340
+
341
+ def bar_chart(labels, data, legends)
342
+ w = Kumiki::BarChart.new(labels, data, legends)
343
+ __dsl_auto_add(w)
344
+ w
345
+ end
346
+
347
+ def line_chart(labels, data, legends)
348
+ w = Kumiki::LineChart.new(labels, data, legends)
349
+ __dsl_auto_add(w)
350
+ w
351
+ end
352
+
353
+ def pie_chart(labels, values)
354
+ w = Kumiki::PieChart.new(labels, values)
355
+ __dsl_auto_add(w)
356
+ w
357
+ end
358
+
359
+ def scatter_chart(x_data, y_data, legends)
360
+ w = Kumiki::ScatterChart.new(x_data, y_data, legends)
361
+ __dsl_auto_add(w)
362
+ w
363
+ end
364
+
365
+ def area_chart(labels, data, legends)
366
+ w = Kumiki::AreaChart.new(labels, data, legends)
367
+ __dsl_auto_add(w)
368
+ w
369
+ end
370
+
371
+ def stacked_bar_chart(labels, data, legends)
372
+ w = Kumiki::StackedBarChart.new(labels, data, legends)
373
+ __dsl_auto_add(w)
374
+ w
375
+ end
376
+
377
+ def gauge_chart(value, min_val, max_val)
378
+ w = Kumiki::GaugeChart.new(value, min_val, max_val)
379
+ __dsl_auto_add(w)
380
+ w
381
+ end
382
+
383
+ def heatmap_chart(x_labels, y_labels, data)
384
+ w = Kumiki::HeatmapChart.new(x_labels, y_labels, data)
385
+ __dsl_auto_add(w)
386
+ w
387
+ end
388
+
389
+ def webview(url: nil, html: nil, **kwargs)
390
+ w = Kumiki::WebViewWidget.new(url: url, html: html)
391
+ __apply_kwargs(w, kwargs, false) if kwargs.length > 0
392
+ __dsl_auto_add(w)
393
+ w
394
+ end
395
+
396
+ # --- Generic embed function ---
397
+
398
+ def embed(w)
399
+ __dsl_auto_add(w)
400
+ w
401
+ end
402
+ end
403
+
404
+ # Auto-include DSL in Component so view() methods can use DSL functions
405
+ class Component
406
+ include Kumiki::DSL
407
+ end
408
+ end