unmagic-components 0.1.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +53 -0
- data/LICENSE +21 -0
- data/README.md +337 -0
- data/app/assets/javascripts/unmagic/components/upsert.js +45 -0
- data/app/assets/stylesheets/unmagic/components.css +382 -0
- data/config/importmap.rb +3 -0
- data/lib/unmagic/components/action_view_helpers.rb +168 -0
- data/lib/unmagic/components/configuration.rb +36 -0
- data/lib/unmagic/components/detail_list/item.rb +31 -0
- data/lib/unmagic/components/detail_list.rb +65 -0
- data/lib/unmagic/components/engine.rb +39 -0
- data/lib/unmagic/components/form_builder.rb +205 -0
- data/lib/unmagic/components/renderers/empty_state.rb +22 -0
- data/lib/unmagic/components/renderers/pagination.rb +62 -0
- data/lib/unmagic/components/table/column.rb +46 -0
- data/lib/unmagic/components/table.rb +254 -0
- data/lib/unmagic/components/table_tag.rb +93 -0
- data/lib/unmagic/components/version.rb +7 -0
- data/lib/unmagic/components.rb +43 -0
- data/lib/unmagic-components.rb +3 -0
- metadata +137 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Unmagic
|
|
4
|
+
module Components
|
|
5
|
+
# Renders a `.UnmagicTable` from plain cells. This is the primitive Table is
|
|
6
|
+
# built on, and it is useful directly for a static table that wants the same
|
|
7
|
+
# look without the record/sort/pagination machinery.
|
|
8
|
+
#
|
|
9
|
+
# A cell is a value, or a { content:, **attrs } hash setting attributes on its
|
|
10
|
+
# th/td. A row is an array of cells, or a { cells:, **attrs } hash setting
|
|
11
|
+
# attributes on its <tr>.
|
|
12
|
+
class TableTag
|
|
13
|
+
ALIGN_CLASSES = { right: "is-right", center: "is-center" }.freeze
|
|
14
|
+
|
|
15
|
+
# A width is either a CSS length, which rides on the <col> as an inline
|
|
16
|
+
# style, or anything else, which is treated as a class name so a host can
|
|
17
|
+
# pin columns with its own utilities (e.g. Tailwind's "w-[40%]").
|
|
18
|
+
CSS_LENGTH = /\A-?[\d.]+(%|px|rem|em|ch|ex|vw|vh|fr)\z/
|
|
19
|
+
|
|
20
|
+
def initialize(view, headers, rows, aligns: [], widths: [], caption: nil, rows_id: nil, **attributes)
|
|
21
|
+
@view = view
|
|
22
|
+
@headers = headers
|
|
23
|
+
@rows = rows
|
|
24
|
+
@aligns = aligns
|
|
25
|
+
@widths = widths
|
|
26
|
+
@caption = caption
|
|
27
|
+
@rows_id = rows_id
|
|
28
|
+
@attributes = attributes
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def render
|
|
32
|
+
attributes = @attributes.dup
|
|
33
|
+
attributes[:class] = class_names("UnmagicTable UnmagicTable--full",
|
|
34
|
+
("UnmagicTable--fixed" if pinned?), attributes[:class])
|
|
35
|
+
|
|
36
|
+
tag.table(**attributes) do
|
|
37
|
+
safe_join [ caption, colgroup, (head if @headers.present?), body ].compact
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# One <tr>, rendered on its own. A broadcast replacing or inserting a single
|
|
42
|
+
# row needs the same markup the table would have produced for it.
|
|
43
|
+
def render_row(row)
|
|
44
|
+
row = { cells: row } unless row.is_a?(Hash)
|
|
45
|
+
cells = Array(row[:cells]).each_with_index.map { |cell, index| render_cell(:td, cell, @aligns[index]) }
|
|
46
|
+
tag.tr safe_join(cells), **row.except(:cells)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
attr_reader :view
|
|
52
|
+
|
|
53
|
+
delegate :tag, :safe_join, :class_names, to: :view, private: true
|
|
54
|
+
|
|
55
|
+
def pinned? = @widths.any?(&:present?)
|
|
56
|
+
|
|
57
|
+
def caption
|
|
58
|
+
tag.caption(@caption, class: "UnmagicTable__caption") if @caption
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def colgroup
|
|
62
|
+
return unless pinned?
|
|
63
|
+
|
|
64
|
+
tag.colgroup safe_join(@widths.map { |width| col(width) })
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def col(width)
|
|
68
|
+
if width.blank?
|
|
69
|
+
tag.col
|
|
70
|
+
elsif width.to_s.match?(CSS_LENGTH)
|
|
71
|
+
tag.col(style: "width: #{width}")
|
|
72
|
+
else
|
|
73
|
+
tag.col(class: width)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def head
|
|
78
|
+
tag.thead tag.tr(safe_join(@headers.each_with_index.map { |cell, index| render_cell(:th, cell, @aligns[index]) }))
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def body
|
|
82
|
+
tag.tbody safe_join(@rows.map { |row| render_row(row) }), id: @rows_id
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def render_cell(name, cell, align)
|
|
86
|
+
cell = { content: cell } unless cell.is_a?(Hash)
|
|
87
|
+
attributes = cell.except(:content)
|
|
88
|
+
attributes[:class] = class_names(ALIGN_CLASSES[align], attributes[:class]).presence
|
|
89
|
+
tag.public_send(name, cell[:content], **attributes)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/core_ext/object/blank"
|
|
4
|
+
require "active_support/core_ext/object/try"
|
|
5
|
+
require "active_support/core_ext/hash/except"
|
|
6
|
+
require "active_support/core_ext/module/delegation"
|
|
7
|
+
require "active_support/core_ext/string/output_safety"
|
|
8
|
+
|
|
9
|
+
require_relative "components/version"
|
|
10
|
+
require_relative "components/configuration"
|
|
11
|
+
require_relative "components/renderers/empty_state"
|
|
12
|
+
require_relative "components/renderers/pagination"
|
|
13
|
+
require_relative "components/table_tag"
|
|
14
|
+
require_relative "components/table/column"
|
|
15
|
+
require_relative "components/table"
|
|
16
|
+
require_relative "components/form_builder"
|
|
17
|
+
require_relative "components/detail_list/item"
|
|
18
|
+
require_relative "components/detail_list"
|
|
19
|
+
require_relative "components/action_view_helpers"
|
|
20
|
+
# ActionView pulls in a partial Rails namespace, so this checks for the constant it
|
|
21
|
+
# actually needs rather than for Rails.
|
|
22
|
+
require_relative "components/engine" if defined?(Rails::Engine)
|
|
23
|
+
|
|
24
|
+
module Unmagic
|
|
25
|
+
module Components
|
|
26
|
+
class << self
|
|
27
|
+
def configure
|
|
28
|
+
yield(configuration) if block_given?
|
|
29
|
+
configuration
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def configuration
|
|
33
|
+
@configuration ||= Configuration.new
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Drops every customisation, restoring the built-in seams. Intended for
|
|
37
|
+
# tests; an app configures once at boot.
|
|
38
|
+
def reset_configuration!
|
|
39
|
+
@configuration = nil
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: unmagic-components
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Keith Pitt
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: activesupport
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '7.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '7.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: actionview
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '7.0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '7.0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: railties
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '7.0'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '7.0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rspec
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '3.12'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '3.12'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: rake
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '13.0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '13.0'
|
|
82
|
+
description: Server-rendered view builders in the spirit of form_for. table_for for
|
|
83
|
+
index tables — sortable headers, deferred turbo-frame loading with a matching skeleton,
|
|
84
|
+
empty states, pagination, and rows a Turbo Stream can keep up to date. detail_list
|
|
85
|
+
for description lists, and a form builder for the chrome around a control. Plain
|
|
86
|
+
Rails helpers, themed through CSS custom properties.
|
|
87
|
+
email:
|
|
88
|
+
- keith@unreasonable-magic.com
|
|
89
|
+
executables: []
|
|
90
|
+
extensions: []
|
|
91
|
+
extra_rdoc_files: []
|
|
92
|
+
files:
|
|
93
|
+
- CHANGELOG.md
|
|
94
|
+
- LICENSE
|
|
95
|
+
- README.md
|
|
96
|
+
- app/assets/javascripts/unmagic/components/upsert.js
|
|
97
|
+
- app/assets/stylesheets/unmagic/components.css
|
|
98
|
+
- config/importmap.rb
|
|
99
|
+
- lib/unmagic-components.rb
|
|
100
|
+
- lib/unmagic/components.rb
|
|
101
|
+
- lib/unmagic/components/action_view_helpers.rb
|
|
102
|
+
- lib/unmagic/components/configuration.rb
|
|
103
|
+
- lib/unmagic/components/detail_list.rb
|
|
104
|
+
- lib/unmagic/components/detail_list/item.rb
|
|
105
|
+
- lib/unmagic/components/engine.rb
|
|
106
|
+
- lib/unmagic/components/form_builder.rb
|
|
107
|
+
- lib/unmagic/components/renderers/empty_state.rb
|
|
108
|
+
- lib/unmagic/components/renderers/pagination.rb
|
|
109
|
+
- lib/unmagic/components/table.rb
|
|
110
|
+
- lib/unmagic/components/table/column.rb
|
|
111
|
+
- lib/unmagic/components/table_tag.rb
|
|
112
|
+
- lib/unmagic/components/version.rb
|
|
113
|
+
homepage: https://github.com/unreasonable-magic/unmagic-components
|
|
114
|
+
licenses:
|
|
115
|
+
- MIT
|
|
116
|
+
metadata:
|
|
117
|
+
homepage_uri: https://github.com/unreasonable-magic/unmagic-components
|
|
118
|
+
changelog_uri: https://github.com/unreasonable-magic/unmagic-components/blob/main/CHANGELOG.md
|
|
119
|
+
rubygems_mfa_required: 'true'
|
|
120
|
+
rdoc_options: []
|
|
121
|
+
require_paths:
|
|
122
|
+
- lib
|
|
123
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
124
|
+
requirements:
|
|
125
|
+
- - ">="
|
|
126
|
+
- !ruby/object:Gem::Version
|
|
127
|
+
version: '3.3'
|
|
128
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
129
|
+
requirements:
|
|
130
|
+
- - ">="
|
|
131
|
+
- !ruby/object:Gem::Version
|
|
132
|
+
version: '0'
|
|
133
|
+
requirements: []
|
|
134
|
+
rubygems_version: 4.0.10
|
|
135
|
+
specification_version: 4
|
|
136
|
+
summary: Declarative table, detail-list and form builders for Rails views
|
|
137
|
+
test_files: []
|