protos 0.5.0 → 0.7.0

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 (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