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.
@@ -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,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unmagic
4
+ module Components
5
+ VERSION = "0.1.0"
6
+ end
7
+ 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
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "unmagic/components"
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: []