protos 0.5.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -0
  3. data/README.md +189 -76
  4. data/examples/list.rb +2 -2
  5. data/examples/navbar.rb +3 -8
  6. data/lib/protos/accordion/item.rb +4 -2
  7. data/lib/protos/accordion.rb +10 -11
  8. data/lib/protos/alert.rb +3 -0
  9. data/lib/protos/attributes.rb +1 -18
  10. data/lib/protos/avatar.rb +10 -10
  11. data/lib/protos/badge.rb +62 -0
  12. data/lib/protos/breadcrumbs.rb +2 -0
  13. data/lib/protos/card.rb +12 -7
  14. data/lib/protos/carousel.rb +13 -10
  15. data/lib/protos/chat_bubble/content.rb +12 -12
  16. data/lib/protos/chat_bubble.rb +11 -6
  17. data/lib/protos/collapse/title.rb +3 -3
  18. data/lib/protos/collapse.rb +10 -7
  19. data/lib/protos/combobox.rb +3 -3
  20. data/lib/protos/command/input.rb +4 -4
  21. data/lib/protos/command.rb +16 -2
  22. data/lib/protos/component.rb +3 -3
  23. data/lib/protos/drawer.rb +7 -3
  24. data/lib/protos/dropdown.rb +10 -6
  25. data/lib/protos/hero.rb +3 -0
  26. data/lib/protos/list.rb +2 -0
  27. data/lib/protos/mix.rb +39 -0
  28. data/lib/protos/modal/close_button.rb +8 -0
  29. data/lib/protos/modal/dialog.rb +4 -6
  30. data/lib/protos/modal.rb +6 -1
  31. data/lib/protos/popover.rb +24 -21
  32. data/lib/protos/stats.rb +7 -0
  33. data/lib/protos/steps.rb +5 -3
  34. data/lib/protos/swap.rb +3 -0
  35. data/lib/protos/table/caption.rb +3 -3
  36. data/lib/protos/table/cell.rb +3 -3
  37. data/lib/protos/table/head.rb +3 -3
  38. data/lib/protos/table.rb +21 -13
  39. data/lib/protos/tabs/tab.rb +4 -4
  40. data/lib/protos/tabs.rb +18 -16
  41. data/lib/protos/theme.rb +8 -7
  42. data/lib/protos/timeline.rb +8 -3
  43. data/lib/protos/toast.rb +5 -3
  44. data/lib/protos/typography/paragraph.rb +3 -3
  45. data/lib/protos/typography.rb +4 -0
  46. data/lib/protos/version.rb +1 -1
  47. data/lib/protos.rb +37 -120
  48. metadata +5 -7
  49. data/lib/protos/command/dialog.rb +0 -40
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 875e55f36d03988e78d0e6834e840094b089ee1e755c003b6483a07a503bfbf4
4
- data.tar.gz: 6b0bdbfc22451928316c73dd931cdeebe3e47cf20c596b3d5318b3145f51b5bc
3
+ metadata.gz: d7486060db2b247fab3e5d5caa33c6f8d35631772e267ae248d8929b71038fbb
4
+ data.tar.gz: ef414faf4cc381245bc9e7b609124858b4a1d1280dfcf5e21a139641d6877f0a
5
5
  SHA512:
6
- metadata.gz: 62c59568bcf8631d3d9c40de57ddb6b1df2f92183c0e9aa92e8be6b0da7d6e325e440a869eda3f1fd0cb93f651f9db8598a9914cc89b6454a1cda7f5a04517fc
7
- data.tar.gz: 2ef45fba8e402133e4345fa91186713dc864e11d737bf3200548340cf7ed3d115e08b406b6d5c98eab8d568d4178b37d1b5e43fa13569dcc873fda6a8f338be9
6
+ metadata.gz: 37c65c3a6be4bfc15fb70e31988a4624c56426e607796de03ae8be9b47be9f016ad27ee4fc508ec57442f6cb0ae8d5d2e27bad40b8b8178c61488935fcafbf9c
7
+ data.tar.gz: 56354393cb9425b3455bcf4baa568a7f23805a226a3b0de75264f505dc9c5f2deee503d77e4b3fd0d7e3ecdef6253daebc5262ba0cb5b7591b6582fec3f96adb
data/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  ## [Unreleased]
2
2
 
3
+ - Changes passing an `input_id` to accordions. Replaced with the more accurate
4
+ `input_name` (optional) parameter. There was no point in having different
5
+ name attributes for the different radio buttons
6
+ - Updates modal component to use newer modal controller from protos-stimulus
7
+ that uses `@stimulus-components/dialog`
8
+ - Adds the ability for `css` helper to take multiple values, including inline
9
+ values instead of theme keys.
10
+ - Adds new `Protos::Badge` component
11
+ - Removes deprecated tokens to prepare for phlex 2.0
12
+ - Removes `dry-initializer` undefined constant to improve performance
13
+ - Adds autoloading constants instead of hard requires
14
+
15
+ ## [0.6.0] - 2024-09-04
16
+
17
+ - Changes how merging attributes works to only mix on certain attributes,
18
+ overriding on all others. This is opposite to how attributes used to be merged
19
+ by default. This is a fix for attributes like `value` where you actually need
20
+ to override them.
21
+ - Adds a separate tested `Mix` class for handling attribute merging
22
+
3
23
  ## [0.5.0] - 2024-08-27
4
24
 
5
25
  - Fixes all accessibility violations according to Axe Core
data/README.md CHANGED
@@ -20,10 +20,91 @@ Other Phlex based UI libraries worth checking out:
20
20
  - [PhlexUI](https://phlexui.com/)
21
21
  - [ZestUI](https://zestui.com/)
22
22
 
23
+ Thinking of making your next static site using Phlex? Check out
24
+ [staticky](https://github.com/nolantait/staticky). The protos docs were
25
+ published using it.
26
+
27
+ ## Phlex components
28
+
29
+ Phlex is a fantastic framework for building frontend components in pure Ruby:
30
+
31
+ ```ruby
32
+ class Navbar
33
+ def view_template
34
+ header(class: "flex items-center justify-between") do
35
+ h3 { "My site" }
36
+ button { "Log out" }
37
+ end
38
+ end
39
+ end
40
+ ```
41
+
42
+ But how can we sometimes render this `Navbar` with a different background color?
43
+
44
+ It would be nice to have our components take a class like any other element:
45
+
46
+ ```ruby
47
+ render Navbar.new(class: "bg-primary")
48
+ ```
49
+
50
+ Unfortunately `class` is a special keyword in Ruby, so we need to do some
51
+ awkward handling to use it like this:
52
+
53
+ ```ruby
54
+ class Navbar
55
+ def initialize(**options)
56
+ # Keyword `class` is a special word in Ruby so we have to awkwardly unwrap
57
+ # like this instead of using keyword arguments
58
+ @classes = options[:class]
59
+ end
60
+
61
+ def view_template
62
+ header(class: "#{@classes} flex items-center justify-between") do
63
+ h3 { "My site" }
64
+ button { "Log out" }
65
+ end
66
+ end
67
+ end
68
+ ```
69
+
70
+ Now we can pass in a style to our container, but what about overriding the style
71
+ of the `h3` tag?
72
+
73
+ ```ruby
74
+ class Navbar
75
+ def initialize(**options)
76
+ # Keyword `class` is a special word in Ruby so we have to awkwardly unwrap
77
+ # like this instead of using keyword arguments
78
+ @container_classes = options[:class]
79
+ @title_classes = options[:title_class]
80
+ end
81
+
82
+ def view_template
83
+ header(class: "#{@classes} flex items-center justify-between") do
84
+ h3(class: @title_classes) { "My site" }
85
+ button { "Log out" }
86
+ end
87
+ end
88
+ end
89
+ ```
90
+
91
+ Eventually everyone makes a kind of ad-hoc system for specifying styles.
92
+
93
+ It gets more complicated when you have attributes like a data-controller. How do
94
+ you give a good experience letting people using your components to add their own
95
+ controllers while your component depends on one already?
96
+
97
+ This library is an attempt to make this kind of developer experience while
98
+ making reusable components more convention over configuration.
99
+
23
100
  ## Protos::Component
24
101
 
25
- A protos component follows some conventions that make them easy to work with as
26
- components in your app.
102
+ A protos component follows 3 conventions that make them easy to work with as
103
+ components in your app:
104
+
105
+ - [Slots and themes](#slots-and-themes)
106
+ - [Attrs and default attrs](#attrs-and-default-attrs)
107
+ - [Params and options](#params-and-options)
27
108
 
28
109
  Every UI component library will have a tension between being too general to fit
29
110
  in your app or too narrow to be useful. Making components that look good out of
@@ -32,20 +113,18 @@ the box can make them hard to customize.
32
113
  We try and resolve this tension by making these components have a minimal style
33
114
  that can be easily overridden using some ergonomic conventions.
34
115
 
35
- There are 3 core conventions:
36
- - [Slots and themes](#slots-and-themes)
37
- - [Attrs and default attrs](#attrs-and-default-attrs)
38
- - [Params and options](#params-and-options)
39
-
40
116
  ### Slots and themes
41
117
 
42
- Components are styled with `css` slots that are filled with values from
43
- a `theme`.
118
+ Components are styled with `css` slots that get their values from a simple hash
119
+ we call a `theme`.
120
+
121
+ You define a `theme` for your component by defining a `#theme` method that
122
+ returns a hash.
123
+
124
+ Users of your components can override, merge, or remove parts of your theme by
125
+ passing in their own as an argument to the component. Another nice benefit is
126
+ that your markup doesn't get overwhelmed horizontally with your css classes.
44
127
 
45
- You define a theme for your component by defining a `#theme` method that returns
46
- a hash. This hash will be merged with any theme provided when rendering your
47
- component. This allows you to easily override styles for your components
48
- depending on their context.
49
128
 
50
129
  ```ruby
51
130
  class List < Protos::Component
@@ -58,7 +137,7 @@ class List < Protos::Component
58
137
 
59
138
  def theme
60
139
  {
61
- list: tokens("space-y-4"), # We can use `#tokens` from phlex (recommended)
140
+ list: ["space-y-4"], # We can use arrays
62
141
  item: "font-bold text-2xl" # Or just plain old strings
63
142
  }
64
143
  end
@@ -66,7 +145,10 @@ end
66
145
  ```
67
146
 
68
147
  Using a theme and css slots allows us to easily override any part of a component
69
- when we render:
148
+ when we render.
149
+
150
+ Here we are passing in our own theme. The default behavior is to add these
151
+ styles on to the theme, rather than replacing them.
70
152
 
71
153
  ```ruby
72
154
  render List.new(
@@ -77,7 +159,12 @@ render List.new(
77
159
  )
78
160
  ```
79
161
 
80
- This would combine the default and our theme using tailwind\_merge:
162
+ When the component is rendered the `tailwind_merge` gem will also prune any
163
+ duplicate unneeded styles.
164
+
165
+ For example even though the themes `list` key would be added together to become
166
+ `space-y-4 space-y-8`, the `tailwind_merge` gem will prune it down to just
167
+ `space-y-8` as the two styles conflict.
81
168
 
82
169
  ```html
83
170
  <ul class="space-y-8">
@@ -119,8 +206,8 @@ The new `css[:item]` slot would be:
119
206
  <li class="font-bold">Item 1</li>
120
207
  ```
121
208
 
122
- If you want to change the method we define our default theme you can override the
123
- `theme_method` on the class:
209
+ If you want to change the method we define our default theme under you can
210
+ override the `theme_method` on the class:
124
211
 
125
212
  ```ruby
126
213
  class List < Protos::Component
@@ -132,22 +219,37 @@ class List < Protos::Component
132
219
 
133
220
  def custom_theme
134
221
  {
135
- list: tokens("space-y-4"),
136
- item: tokens("font-bold", "text-2xl")
222
+ list: "space-y-4",
223
+ item: ["font-bold", "text-2xl"]
137
224
  }
138
225
  end
139
226
  end
140
227
  ```
141
228
 
229
+ Slots can also take multiple arguments, and even inline styles:
230
+
231
+ ```ruby
232
+ class ListItem < Protos::Component
233
+ def view_template
234
+ li(class: css[:item, :primary_item, "text-sm"])
235
+ end
236
+ end
237
+ ```
238
+
239
+ This combines the styles together, removing any duplicates.
240
+
142
241
  ### Attrs and default attrs
143
242
 
144
243
  By convention, all components spread in an `attrs` hash on their outermost
145
- element of the component.
244
+ element of the component. There is no rule for this, but it makes them feel more
245
+ naturally like native html elements when you render them.
146
246
 
147
- By doing this we enable 2 main conveniences:
247
+ By doing this we enable 3 main conveniences:
148
248
  1. We can pass a `class` keyword when initializing the component which will be
149
249
  merged safely into the `css[:container]` slot
150
- 2. We can add default attributes that are safely merged with any provided to the
250
+ 2. We can pass any html attributes we want to the element such as `id`, `data`
251
+ etc and it will just work
252
+ 3. We can add default attributes that are safely merged with any provided to the
151
253
  component when its being initialized
152
254
 
153
255
  ```ruby
@@ -168,19 +270,22 @@ class List < Protos::Component
168
270
 
169
271
  def theme
170
272
  {
171
- container: tokens("space-y-4"),
172
- item: tokens("font-bold")
273
+ container: "space-y-4",
274
+ item: "font-bold"
173
275
  }
174
276
  end
175
277
  end
176
278
  ```
177
279
 
178
- `#attrs` will by default merge the `class` keyword into the `css[:container]`
179
- slot which we define in our theme.
280
+ `#attrs` returns a hash which will by default merge the `class` keyword into the
281
+ `css[:container]` slot which we define in our theme. The `ul` elements class
282
+ would be `space-y-4` as that is the `css[:container]` on our theme.
283
+
284
+ Special html options (`class`, `data`) will be safely merged.
180
285
 
181
- Special html options will be safely merged. For examples, the component above
182
- defines a list controller. If we passed our own controller into data when we
183
- initialize, the component's data-controller attribute would be appended to:
286
+ For examples, the component above defines a list controller. If we passed our
287
+ own controller into data when we initialize, the component's data-controller
288
+ attribute would be appended to:
184
289
 
185
290
  ```ruby
186
291
  render List.new(
@@ -194,6 +299,9 @@ That would output both controllers to the DOM element:
194
299
  <ul data-controller="list tooltip">
195
300
  ```
196
301
 
302
+ This makes it very convenient to add functionality to basic components without
303
+ overriding their core behavior or having to modify/override their class.
304
+
197
305
  If we wanted to, just like for our theme we can change the method from
198
306
  `default_attrs` by defining the `default_attrs_method` on the class:
199
307
 
@@ -224,25 +332,27 @@ class List < Protos::Component
224
332
  end
225
333
  ```
226
334
 
335
+ This makes our initialization declarative and easy to extend without having to
336
+ consider how to call `super` in the initializer.
337
+
227
338
  The following keywords are reserved in the base class:
228
339
 
229
340
  - `class`
230
341
  - `theme`
231
342
  - `html_options`
232
343
 
344
+ You are free to add whatever positional or keyword arguments you like as long as
345
+ they don't directly conflict with those names.
346
+
233
347
  ## Putting it all together
234
348
 
235
- Here is an example of a small navbar component:
349
+ Lets revisit the example of our `Navbar` component:
236
350
 
237
351
  ```ruby
238
352
  require "protos"
239
353
 
240
354
  class Navbar < Protos::Component
241
355
  def view_template
242
- # **attrs will add:
243
- # - Any html options defined on the component initialization such as data,
244
- # role, for, etc..
245
- # - Class will be added to the css[:container] and applied
246
356
  header(**attrs) do
247
357
  h1(class: css[:heading]) { "Hello world" }
248
358
  h2(class: css[:subtitle]) { "With a subtitle" }
@@ -259,19 +369,19 @@ class Navbar < Protos::Component
259
369
 
260
370
  def theme
261
371
  {
262
- container: tokens(
263
- "flex",
264
- "justify-between",
265
- "items-center",
266
- "gap-sm"
267
- ),
268
- heading: tokens("text-2xl", "font-bold"),
269
- subtitle: tokens("text-base")
372
+ container: "flex justify-between items-center gap-sm",
373
+ heading: "text-2xl font-bold",
374
+ subtitle: "text-sm"
270
375
  }
271
376
  end
272
377
  end
378
+ ```
379
+
380
+ Now all the concerns about adding in our behavior, styles, etc are handled for
381
+ us by convention:
273
382
 
274
- component = Navbar.new(
383
+ ```ruby
384
+ render Navbar.new(
275
385
  # This will add to the component's css[:container] slot
276
386
  class: "my-sm",
277
387
  # This will add the controller and not remove
@@ -283,8 +393,6 @@ component = Navbar.new(
283
393
  subtitle!: "text-xl" # We can override the entire slot
284
394
  }
285
395
  )
286
-
287
- puts component.call
288
396
  ```
289
397
 
290
398
  Which produces the following html:
@@ -308,7 +416,7 @@ If bundler is not being used to manage dependencies, install the gem by executin
308
416
 
309
417
  ## Usage
310
418
 
311
- Setup [Tailwindcss](https://tailwindcss.com/), [daisyUI](https://daisyui.com)
419
+ Setup [TailwindCSS](https://tailwindcss.com/), [DaisyUI](https://daisyui.com)
312
420
  and add the protos path to your content.
313
421
 
314
422
  ```
@@ -316,7 +424,7 @@ npm install -D tailwindcss postcss autoprefixer daisyui
316
424
  npx tailwindcss init
317
425
  ```
318
426
 
319
- Then we need to add the protos path to the `content` of our tailwindcss config
427
+ Then we need to add the protos path to the `content` of our tailwind config
320
428
  so tailwind will read the styles defined in the Protos gem.
321
429
 
322
430
  Protos also uses semantic spacing such as `p-sm` or `m-md` instead of set
@@ -344,15 +452,6 @@ module.exports = {
344
452
  lg: "var(--spacing-lg)",
345
453
  xl: "var(--spacing-xl)",
346
454
  },
347
- // If you use % based spacing you might want different spacing
348
- // for any vertical gaps to prevent overflow
349
- gap: {
350
- xs: "var(--spacing-gap-xs)",
351
- sm: "var(--spacing-gap-sm)",
352
- md: "var(--spacing-gap-md)",
353
- lg: "var(--spacing-gap-lg)",
354
- xl: "var(--spacing-gap-xl)",
355
- },
356
455
  },
357
456
  }
358
457
  // ....
@@ -388,11 +487,12 @@ end
388
487
 
389
488
  ## Building your own components
390
489
 
391
- You can override components simply by redefining the class in your own app:
490
+ You can override components simply by redefining sub-classing the class in your
491
+ own app:
392
492
 
393
493
  ```ruby
394
- module Protos
395
- class Swap < Component
494
+ module Components
495
+ class Swap < Protos::Component
396
496
  private
397
497
 
398
498
  def on(...)
@@ -401,15 +501,29 @@ module Protos
401
501
 
402
502
  def theme
403
503
  super.merge({
404
- input: tokens("block", "bg-red-500")
504
+ input: ["block", "bg-red-500"]
405
505
  })
406
506
  end
407
507
  end
408
508
  end
409
509
  ```
410
510
 
411
- You could also encapsulate these more primitive proto components into your own
412
- components. You could use `Proto::List` to create your own list and even use
511
+ But its much better to avoid the sub-classing and just render the component
512
+ inside of your own:
513
+
514
+ ```ruby
515
+ module Components
516
+ class Swap < ApplicationComponent
517
+ def view_template
518
+ render Protos::Swap.new do |c|
519
+ # ....
520
+ end
521
+ end
522
+ end
523
+ end
524
+ ```
525
+
526
+ You could use `Proto::List` to create your own list and even use
413
527
  `Phlex::DeferredRender` to make the API more convenient.
414
528
 
415
529
  Let's create a list component with headers and actions:
@@ -460,11 +574,11 @@ module Ui
460
574
 
461
575
  def theme
462
576
  {
463
- container: tokens("space-y-xs"),
464
- header: tokens("flex", "justify-between", "items-end", "gap-sm"),
465
- list: tokens("divide-y", "border", "w-full"),
466
- actions: tokens("space-x-xs"),
467
- item: tokens("p-sm")
577
+ container: "space-y-xs",
578
+ header: "flex justify-between items-end gap-sm",
579
+ list: "divide-y border w-full",
580
+ actions: "space-x-xs",
581
+ item: "p-sm"
468
582
  }
469
583
  end
470
584
  end
@@ -575,10 +689,10 @@ module Ui
575
689
 
576
690
  def theme
577
691
  {
578
- container: tokens("space-y-sm"),
579
- header: tokens("flex", "justify-between", "items-end", "gap-sm"),
580
- table: tokens("border"),
581
- caption: tokens("text-muted")
692
+ container: "space-y-sm",
693
+ header: "flex justify-between items-end gap-sm",
694
+ table: "border",
695
+ caption: "text-muted"
582
696
  }
583
697
  end
584
698
  end
@@ -613,12 +727,11 @@ render Ui::Table.new(title: "A table", collection:) do |table|
613
727
  end
614
728
  ```
615
729
 
616
- ## No unnecessary components
730
+ ## Missing components
617
731
 
618
- This library avoids re-making Protos components for extremely simple daisyui
619
- components such as:
732
+ This library tries to avoid re-making Protos components for extremely simple
733
+ DaisyUI components. Here is a list that we don't yet have components for:
620
734
 
621
- - Badge
622
735
  - Buttons
623
736
  - Checkbox
624
737
  - File input
data/examples/list.rb CHANGED
@@ -20,8 +20,8 @@ class List < Protos::Component
20
20
 
21
21
  def theme
22
22
  {
23
- container: tokens("space-y-4"),
24
- item: tokens("font-bold")
23
+ container: "space-y-4",
24
+ item: "font-bold"
25
25
  }
26
26
  end
27
27
  end
data/examples/navbar.rb CHANGED
@@ -20,14 +20,9 @@ class Navbar < Protos::Component
20
20
 
21
21
  def theme
22
22
  {
23
- container: tokens(
24
- "flex",
25
- "justify-between",
26
- "items-center",
27
- "gap-sm"
28
- ),
29
- heading: tokens("text-2xl", "font-bold"),
30
- subtitle: tokens("text-base")
23
+ container: "flex justify-between items-center gap-sm",
24
+ heading: "text-2xl font-bold",
25
+ subtitle: "text-base"
31
26
  }
32
27
  end
33
28
  end
@@ -5,13 +5,15 @@ module Protos
5
5
  class Item < Component
6
6
  # DOCS: An accorion is just a collapse with radio buttons.
7
7
 
8
- option :input_id, type: Types::String | Types::Integer
8
+ option :input_name,
9
+ type: Types::String | Types::Integer | Types::Nil,
10
+ reader: false
9
11
 
10
12
  def view_template(&block)
11
13
  li(**attrs) do
12
14
  render Collapse.new(
13
15
  theme: collapse_theme,
14
- input_id: @input_id.to_s,
16
+ input_name: @input_name,
15
17
  input_type: :radio,
16
18
  &block
17
19
  )
@@ -7,30 +7,29 @@ module Protos
7
7
  # to be open at the same time, use the collapse component.
8
8
  # https://daisyui.com/components/accordion/
9
9
 
10
+ autoload :Item, "protos/accordion/item"
11
+
12
+ option :input_name,
13
+ default: -> { "accordion-#{SecureRandom.hex(4)}" },
14
+ reader: false,
15
+ type: Types::String
16
+
10
17
  def view_template(&)
11
18
  ul(**attrs, &)
12
19
  end
13
20
 
14
- def item(*, input_id: nil, **, &)
15
- self.current_input_id = input_id
16
-
17
- render Item.new(*, input_id: current_input_id, **, &)
21
+ def item(*, **, &)
22
+ render Item.new(*, input_name: @input_name, **, &)
18
23
  end
19
24
 
20
25
  def content(...) = render Collapse::Content.new(...)
21
26
 
22
27
  def title(*, **, &)
23
- render Collapse::Title.new(*, input_id: current_input_id, **, &)
28
+ render Collapse::Title.new(*, input_id: @input_name, **, &)
24
29
  end
25
30
 
26
31
  private
27
32
 
28
- attr_reader :current_input_id
29
-
30
- def current_input_id=(value)
31
- @current_input_id = value || "collapse-#{SecureRandom.hex(4)}"
32
- end
33
-
34
33
  def theme
35
34
  {
36
35
  container: "join join-vertical"
data/lib/protos/alert.rb CHANGED
@@ -6,6 +6,9 @@ module Protos
6
6
  # be used in combination with Protos::Toast to have popup notifications.
7
7
  # https://daisyui.com/components/alert/
8
8
 
9
+ autoload :Actions, "protos/alert/actions"
10
+ autoload :Icon, "protos/alert/icon"
11
+
9
12
  Styles = Types::Coercible::Symbol.enum(
10
13
  :info,
11
14
  :success,
@@ -4,11 +4,6 @@ module Protos
4
4
  class Attributes
5
5
  # DOCS: A class that represents the attributes of a component. This would be
6
6
  # all html options except for `class` and `theme`.
7
- #
8
- # This class is responsible for safely merging in both user supplied and
9
- # default attributes. When a user adds { data: { controller: "foo" }} to
10
- # their component. This will merge the value in so that any default
11
- # controllers do not get overridden.
12
7
 
13
8
  def initialize(attrs = {}, **kwargs)
14
9
  @attrs = attrs.merge!(kwargs)
@@ -34,19 +29,7 @@ module Protos
34
29
  private
35
30
 
36
31
  def mix(hash, *hashes)
37
- hashes.each_with_object(hash) do |hash, result|
38
- result.merge!(hash) do |_key, a, b| # rubocop:disable Metrics/ParameterLists
39
- next a unless b
40
- next a if a == b
41
-
42
- case [a, b]
43
- in String, String then "#{a} #{b}"
44
- in Array, Array then a + b
45
- in Hash, Hash then mix(a, b)
46
- else b
47
- end
48
- end
49
- end
32
+ Mix.call(hash, *hashes)
50
33
  end
51
34
  end
52
35
  end
data/lib/protos/avatar.rb CHANGED
@@ -64,13 +64,13 @@ module Protos
64
64
 
65
65
  option :placeholder, type: Types::Bool, default: -> { false }
66
66
  option :indicator,
67
- type: Indicators,
68
- default: -> { :none },
69
- reader: false
67
+ type: Indicators,
68
+ default: -> { :none },
69
+ reader: false
70
70
  option :shape,
71
- type: MaskShapes,
72
- default: -> { :none },
73
- reader: false
71
+ type: MaskShapes,
72
+ default: -> { :none },
73
+ reader: false
74
74
 
75
75
  def view_template(&block)
76
76
  div(**attrs) do
@@ -90,12 +90,12 @@ module Protos
90
90
 
91
91
  def theme
92
92
  {
93
- container: tokens(
93
+ container: [
94
94
  "avatar",
95
95
  indicator,
96
- placeholder: "placeholder"
97
- ),
98
- figure: tokens(shape)
96
+ ("placeholder" if placeholder)
97
+ ],
98
+ figure: shape
99
99
  }
100
100
  end
101
101
  end