senren-ui 0.1.4 → 0.1.6
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +49 -2
- data/CONTRIBUTING.md +41 -8
- data/README.md +73 -11
- data/docs/components.md +222 -0
- data/docs/performance_testing.md +34 -0
- data/lib/commands/senren/add/add_command.rb +35 -0
- data/lib/generators/senren/install/install_generator.rb +4 -7
- data/lib/generators/senren/install/templates/base_component.rb.tt +39 -6
- data/lib/generators/senren/install/templates/conventions.md.tt +22 -8
- data/lib/senren/rails/agent_rules_writer.rb +175 -0
- data/lib/senren/rails/component_copier.rb +75 -6
- data/lib/senren/rails/component_installer.rb +47 -0
- data/lib/senren/rails/doctor.rb +26 -13
- data/lib/senren/rails/host_paths.rb +12 -3
- data/lib/senren/rails/installer.rb +4 -2
- data/lib/senren/rails/llms_writer.rb +5 -132
- data/lib/senren/rails/registry.rb +63 -31
- data/lib/senren/rails/skill_writer.rb +1 -1
- data/lib/senren/rails/version.rb +1 -1
- data/lib/senren/rails.rb +2 -0
- data/lib/tasks/senren.rake +26 -21
- data/templates/components/billing_plan_card/billing_plan_card_component.html.erb +1 -1
- data/templates/components/breadcrumb/breadcrumb_component.rb +2 -2
- data/templates/components/button/button_component.html.erb +1 -1
- data/templates/components/carousel/carousel_component.rb +1 -1
- data/templates/components/command/command_component.rb +1 -1
- data/templates/components/dropdown_menu/dropdown_menu_component.rb +10 -7
- data/templates/components/form/form_component.html.erb +8 -1
- data/templates/components/form/form_component.rb +3 -1
- data/templates/components/input/input_component.html.erb +1 -1
- data/templates/components/input/input_component.rb +19 -0
- data/templates/components/label/label_component.html.erb +1 -2
- data/templates/components/label/label_component.rb +12 -2
- data/templates/components/link/link_component.html.erb +1 -1
- data/templates/components/native_select/native_select_component.html.erb +19 -5
- data/templates/components/native_select/native_select_component.rb +17 -5
- data/templates/components/pagination/pagination_component.rb +2 -1
- data/templates/components/sidebar/sidebar_component.rb +2 -2
- data/templates/components/switch/switch_component.html.erb +2 -2
- data/templates/components/top_nav/top_nav_component.rb +2 -2
- data/templates/controllers/rich_text_editor_lite_controller.js +12 -2
- metadata +23 -4
|
@@ -13,20 +13,23 @@ module Senren
|
|
|
13
13
|
lg: 'h-12 text-base px-4'
|
|
14
14
|
}.freeze
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
# native_arrow: true → keep browser/OS native arrow (appearance-auto)
|
|
17
|
+
# native_arrow: false → use custom SVG arrow (appearance-none + SVG overlay)
|
|
18
|
+
def initialize(name:, options:, selected: nil, id: nil, prompt: nil, native_arrow: true,
|
|
19
|
+
variant: :default, size: :md, class_name: nil, **html)
|
|
18
20
|
super(variant: variant, size: size, class_name: class_name, **html)
|
|
19
21
|
@name = name
|
|
20
22
|
@options = options
|
|
21
23
|
@selected = selected
|
|
22
24
|
@id = id || name.to_s.parameterize
|
|
23
25
|
@prompt = prompt
|
|
26
|
+
@native_arrow = native_arrow
|
|
24
27
|
end
|
|
25
28
|
|
|
26
29
|
attr_reader :name, :options, :selected, :id, :prompt
|
|
27
30
|
|
|
28
|
-
def
|
|
29
|
-
|
|
31
|
+
def native_arrow?
|
|
32
|
+
@native_arrow
|
|
30
33
|
end
|
|
31
34
|
|
|
32
35
|
def select_attrs
|
|
@@ -39,9 +42,18 @@ module Senren
|
|
|
39
42
|
)
|
|
40
43
|
end
|
|
41
44
|
|
|
45
|
+
def root_select_attrs
|
|
46
|
+
attrs = select_attrs
|
|
47
|
+
data = (attrs[:data] || {}).merge(senren_component: senren_component_name)
|
|
48
|
+
|
|
49
|
+
attrs.merge(data: data)
|
|
50
|
+
end
|
|
51
|
+
|
|
42
52
|
def select_classes
|
|
53
|
+
appearance = native_arrow? ? 'appearance-auto' : 'appearance-none pr-9'
|
|
43
54
|
[
|
|
44
|
-
'
|
|
55
|
+
'w-full cursor-pointer rounded-(--senren-radius) border bg-[hsl(var(--senren-background))] text-[hsl(var(--senren-foreground))] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50',
|
|
56
|
+
appearance,
|
|
45
57
|
self.class::VARIANTS[variant],
|
|
46
58
|
self.class::SIZES[size],
|
|
47
59
|
class_name,
|
|
@@ -18,7 +18,8 @@ module Senren
|
|
|
18
18
|
def page_url(page)
|
|
19
19
|
return '#' unless path
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
safe_page = page.to_i.clamp(1, total_pages)
|
|
22
|
+
safe_url(path.respond_to?(:call) ? path.call(safe_page) : path.to_s.gsub(':page', safe_page.to_s))
|
|
22
23
|
end
|
|
23
24
|
end
|
|
24
25
|
end
|
|
@@ -24,12 +24,12 @@ module Senren
|
|
|
24
24
|
if item.is_a?(Hash)
|
|
25
25
|
{
|
|
26
26
|
label: item[:label] || item['label'],
|
|
27
|
-
href: item[:href] || item['href']
|
|
27
|
+
href: safe_url(item[:href] || item['href']),
|
|
28
28
|
active: item[:active] || item['active']
|
|
29
29
|
}
|
|
30
30
|
else
|
|
31
31
|
label, href = item
|
|
32
|
-
{ label: label, href: href
|
|
32
|
+
{ label: label, href: safe_url(href), active: false }
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
<%= tag.label(**root_attrs("inline-flex items-center gap-3 cursor-pointer")) do %>
|
|
2
2
|
<span class="relative inline-flex h-6 w-11 items-center rounded-full bg-[hsl(var(--senren-muted))] has-[:checked]:bg-[hsl(var(--senren-primary))] transition-colors">
|
|
3
3
|
<input type="checkbox" role="switch" id="<%= id %>" name="<%= name %>" value="<%= value %>" <%= "checked" if checked %> class="peer sr-only">
|
|
4
4
|
<span aria-hidden="true" class="absolute left-0.5 top-0.5 inline-block h-5 w-5 transform rounded-full bg-[hsl(var(--senren-background))] transition-transform peer-checked:translate-x-5"></span>
|
|
@@ -8,4 +8,4 @@
|
|
|
8
8
|
<% else %>
|
|
9
9
|
<%= content %>
|
|
10
10
|
<% end %>
|
|
11
|
-
|
|
11
|
+
<% end %>
|
|
@@ -31,12 +31,12 @@ module Senren
|
|
|
31
31
|
if item.is_a?(Hash)
|
|
32
32
|
{
|
|
33
33
|
label: item[:label] || item['label'],
|
|
34
|
-
href: item[:href] || item['href']
|
|
34
|
+
href: safe_url(item[:href] || item['href']),
|
|
35
35
|
active: item[:active] || item['active']
|
|
36
36
|
}
|
|
37
37
|
else
|
|
38
38
|
label, href = item
|
|
39
|
-
{ label: label, href: href
|
|
39
|
+
{ label: label, href: safe_url(href), active: false }
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
42
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Controller } from "@hotwired/stimulus"
|
|
2
2
|
|
|
3
|
+
const ALLOWED_LINK_PROTOCOLS = new Set(["http:", "https:", "mailto:", "tel:"])
|
|
4
|
+
|
|
3
5
|
// senren--rich-text-editor-lite
|
|
4
6
|
// Local UI: tiny contenteditable toolbar synced to a hidden textarea.
|
|
5
7
|
export default class extends Controller {
|
|
@@ -280,8 +282,16 @@ export default class extends Controller {
|
|
|
280
282
|
normalizeUrl(rawUrl) {
|
|
281
283
|
const url = String(rawUrl || "").trim()
|
|
282
284
|
if (url.length === 0) return null
|
|
283
|
-
if (
|
|
284
|
-
return
|
|
285
|
+
if (url.startsWith("#")) return url
|
|
286
|
+
if (url.startsWith("/") && !url.startsWith("//")) return url
|
|
287
|
+
|
|
288
|
+
const candidate = /^[a-z][a-z0-9+.-]*:/i.test(url) ? url : `https://${url}`
|
|
289
|
+
try {
|
|
290
|
+
const parsed = new URL(candidate, window.location.origin)
|
|
291
|
+
return ALLOWED_LINK_PROTOCOLS.has(parsed.protocol) ? parsed.href : null
|
|
292
|
+
} catch (_) {
|
|
293
|
+
return null
|
|
294
|
+
}
|
|
285
295
|
}
|
|
286
296
|
|
|
287
297
|
activeRange() {
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: senren-ui
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- vutt
|
|
@@ -9,6 +9,20 @@ bindir: bin
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: nokogiri
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 1.19.3
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 1.19.3
|
|
12
26
|
- !ruby/object:Gem::Dependency
|
|
13
27
|
name: rails
|
|
14
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -29,14 +43,14 @@ dependencies:
|
|
|
29
43
|
requirements:
|
|
30
44
|
- - ">="
|
|
31
45
|
- !ruby/object:Gem::Version
|
|
32
|
-
version:
|
|
46
|
+
version: 4.9.0
|
|
33
47
|
type: :runtime
|
|
34
48
|
prerelease: false
|
|
35
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
50
|
requirements:
|
|
37
51
|
- - ">="
|
|
38
52
|
- !ruby/object:Gem::Version
|
|
39
|
-
version:
|
|
53
|
+
version: 4.9.0
|
|
40
54
|
description: |
|
|
41
55
|
Senren UI is a Rails-native UI component library inspired by the developer
|
|
42
56
|
experience of shadcn/ui. It ships generators, a registry, and a centralized
|
|
@@ -53,7 +67,10 @@ files:
|
|
|
53
67
|
- LICENSE
|
|
54
68
|
- README.md
|
|
55
69
|
- Rakefile
|
|
70
|
+
- docs/components.md
|
|
71
|
+
- docs/performance_testing.md
|
|
56
72
|
- docs/visual_style.md
|
|
73
|
+
- lib/commands/senren/add/add_command.rb
|
|
57
74
|
- lib/generators/senren/component/component_generator.rb
|
|
58
75
|
- lib/generators/senren/component/templates/component.html.erb.tt
|
|
59
76
|
- lib/generators/senren/component/templates/component.rb.tt
|
|
@@ -66,7 +83,9 @@ files:
|
|
|
66
83
|
- lib/generators/senren/install/templates/installed_components.yml.tt
|
|
67
84
|
- lib/generators/senren/install/templates/senren.css.tt
|
|
68
85
|
- lib/senren/rails.rb
|
|
86
|
+
- lib/senren/rails/agent_rules_writer.rb
|
|
69
87
|
- lib/senren/rails/component_copier.rb
|
|
88
|
+
- lib/senren/rails/component_installer.rb
|
|
70
89
|
- lib/senren/rails/doctor.rb
|
|
71
90
|
- lib/senren/rails/engine.rb
|
|
72
91
|
- lib/senren/rails/host_paths.rb
|
|
@@ -244,7 +263,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
244
263
|
requirements:
|
|
245
264
|
- - ">="
|
|
246
265
|
- !ruby/object:Gem::Version
|
|
247
|
-
version: 3.
|
|
266
|
+
version: 3.2.0
|
|
248
267
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
249
268
|
requirements:
|
|
250
269
|
- - ">="
|