essence 0.2.2 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f9be2e0f4b7e7288c5cf845c54d67988f472a967ebdd04b6d01ac790c1d1c7a4
4
- data.tar.gz: f1ebff9a5f1f108042f48f3241edc2cd5d8998d9605b20d6e52bed3b338219dc
3
+ metadata.gz: 8a05b5cc8ee41e915b4d8646bb7357451484b0d36f9893deb21f58c540838d86
4
+ data.tar.gz: 27b53f351c8b5fb5b6718cdf2c5b4b4834251042dc48657dd2a70ac42e4865be
5
5
  SHA512:
6
- metadata.gz: 067d0df4723dd420b5100d7c21c417f37e959e62e325154fcd3671a22b3b919d51720e6b6a911233a8791065d0a3a93a9b931c0111b5e4b90454aa6c8648b80c
7
- data.tar.gz: 06d8732651332803411614ae867fd3e78ae226853992fd3d0367bc441054925d6647d4c2151d0c3e0af4b24990b8a24891c8042f816789cd454cda9f5197e03d
6
+ metadata.gz: 1f3d8aad9655e9a3d86ca7db39d6bdc03f608bfe6bc79f6cea64591340449b19fa4c9ffbbfe0f8939472b870dcf57508f1a1b0d9d29504757b49e3636ef3c074
7
+ data.tar.gz: 846b1a2df22849a2c8cdb9b8d44a8e7dbc3204e4b90e68b93b8d355ae6aa86076da3206c00594a54d23b714b37562cf38a5e9070bcaf9e590d3120a372dceb16
data/README.md CHANGED
@@ -14,10 +14,10 @@ A simple, ergonomic and performant component library for Ruby applications.
14
14
 
15
15
  ### Features
16
16
 
17
- - Tailored components - Designed using flexibility in mind while streamlining the development process
18
- - Gorgeous simplicity - Essence empowers minimalistic user interface with purposeful accents
19
- - Geared for performance - Keep everything in one place. No spreadsheets or getting lost between tooling
20
- - Ergonomic approach - Essence is designed to be easy to use and understand
17
+ - Tailored components - Flexible by design while streamlining the development process
18
+ - Gorgeous simplicity - Empowers minimalistic user interface with purposeful accents
19
+ - Geared for performance - Built with performance in mind
20
+ - Ergonomic approach - Designed to be easy to use and understand
21
21
 
22
22
  ---
23
23
 
@@ -45,6 +45,7 @@ More information on about the installation can be found in the [documentation](h
45
45
 
46
46
  - [Mintis](https://mintis.app)
47
47
  - [Hansa](https://hansahq.com)
48
+ - [Oversee](https://github.com/primevise/oversee)
48
49
  - [Release Server](https://releaseserver.com)
49
50
  - [College Life Work](https://work.collegelife.co)
50
51
 
@@ -9,8 +9,16 @@ module Essence
9
9
 
10
10
  def call(*args)
11
11
  component_name = args[0][:component_name]
12
+ key = component_name.to_sym
13
+ has_stimulus_controller = Essence.components[key][:stimulus] || false
12
14
 
13
- return puts "> #{component_name}: component unsupported" unless Essence.component_names.include?(component_name.to_sym)
15
+ return puts "> #{component_name}: component unsupported" unless Essence.component_keys.include?(key)
16
+ puts "> [Essence] #{Essence.components[key][:name]}"
17
+
18
+ if has_stimulus_controller
19
+ Essence::CLI::Commands.copy_controller(component_name:)
20
+ puts "> [Stimulus] #{Essence::CLI::Commands::STIMULUS_CONTROLLERS_DESTINATION_DIR.join("#{component_name}_controller.js")}"
21
+ end
14
22
 
15
23
  Essence::CLI::Commands.copy_component(component_name:)
16
24
  Essence::CLI::Commands.replace_component_contents(component_name:)
@@ -20,7 +28,7 @@ module Essence
20
28
  to: Essence::CLI::Commands::PHLEX_COMPONENT_DEFINITION_SUFFIX
21
29
  )
22
30
 
23
- puts "> Successfully added #{component_name} component to #{Essence::CLI::Commands::DESTINATION_DIR.join("#{component_name}.rb")}"
31
+ puts "> [Phlex] #{Essence::CLI::Commands::DESTINATION_DIR.join("#{component_name}.rb")}"
24
32
  end
25
33
  end
26
34
  end
data/lib/essence/cli.rb CHANGED
@@ -17,8 +17,12 @@ module Essence
17
17
  extend Dry::CLI::Registry
18
18
 
19
19
  # Constants
20
+ STIMULUS_CONTROLLERS_DIR = Pathname.new(::Essence.root_path).join("essence/stimulus")
21
+ STIMULUS_CONTROLLERS_DESTINATION_DIR = Pathname.new(File.expand_path(Dir.pwd)).join(::Essence.configuration.stimulus_controller_path)
22
+
20
23
  COMPONENTS_DIR = Pathname.new(File.expand_path("components", __dir__))
21
- DESTINATION_DIR = Pathname.new(File.expand_path(Dir.pwd)).join("app/components")
24
+ DESTINATION_DIR = Pathname.new(File.expand_path(Dir.pwd)).join(::Essence.configuration.phlex_components_path)
25
+
22
26
  COMPONENT_DEFINITION_PREFIX = "class Essence::"
23
27
  COMPONENT_DEFINITION_SUFFIX = "< Essence::Essence"
24
28
  PHLEX_COMPONENT_DEFINITION_PREFIX = "class Components::"
@@ -32,6 +36,7 @@ module Essence
32
36
  private
33
37
 
34
38
  # UTILITIES
39
+ # PHLEX COMPONENTS
35
40
  def self.copy_component(component_name:)
36
41
  source_path = COMPONENTS_DIR.join("#{component_name}.rb")
37
42
  destination_path = DESTINATION_DIR.join("#{component_name}.rb")
@@ -58,6 +63,15 @@ module Essence
58
63
 
59
64
  FileUtils.mv(from, to)
60
65
  end
66
+
67
+ # STIMULUS CONTROLLERS
68
+ def self.copy_controller(component_name:)
69
+ source_path = STIMULUS_CONTROLLERS_DIR.join("#{component_name}_controller.js")
70
+ destination_path = STIMULUS_CONTROLLERS_DESTINATION_DIR.join("#{component_name}_controller.js")
71
+
72
+ FileUtils.mkdir_p(STIMULUS_CONTROLLERS_DESTINATION_DIR)
73
+ FileUtils.copy(source_path, destination_path)
74
+ end
61
75
  end
62
76
  end
63
77
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Essence::Accordion < Essence::Essence
4
+ BASE = "group py-4"
5
+ TRIGGER_BASE = "cursor-pointer list-none flex items-center justify-between text-base font-medium"
6
+ CONTENT_BASE = "py-2 transform transition-all duration-500 not-open:-mt-4 opacity-0 group-open:opacity-100 group-open:mt-0 text-sm"
7
+ CHEVRON_BASE = "transform transition-all duration-300 rotate-90 group-open:-rotate-90 text-lg text-gray-700"
8
+
9
+ attr_reader :attributes
10
+
11
+ def initialize(**attributes)
12
+ super(**attributes)
13
+ @attributes[:class] = merge_classes([ BASE, @attributes[:class]])
14
+ end
15
+
16
+ def view_template(&)
17
+ details(class: "w-full group py-4", &) if block_given?
18
+ end
19
+
20
+ def trigger(**tattributes, &)
21
+ summary(class: merge_classes(TRIGGER_BASE, tattributes[:class])) do
22
+ p(class: "inline", &)
23
+ span(class: CHEVRON_BASE) { "›" }
24
+ end
25
+ end
26
+
27
+ def content(**cattributes, &)
28
+ p(class: merge_classes(CONTENT_BASE, cattributes[:class]), &)
29
+ end
30
+
31
+ private
32
+
33
+ def merge_classes(*classes)
34
+ TAILWIND_MERGER.merge([ *classes ].compact)
35
+ end
36
+ end
@@ -13,9 +13,9 @@ class Essence::Avatar < Essence::Essence
13
13
  attr_reader :size
14
14
 
15
15
  def initialize(size: :md, **attributes)
16
+ super(**attributes)
16
17
  @size = size
17
- @attributes = attributes
18
- @attributes[:class] = construct_classes(@attributes[:class])
18
+ @attributes[:class] = merge_classes([ BASE, SIZES[size], @attributes[:class]])
19
19
  end
20
20
 
21
21
  def view_template(&)
@@ -28,8 +28,4 @@ class Essence::Avatar < Essence::Essence
28
28
  def fallback(**attrs, &)
29
29
  div(**attrs, &)
30
30
  end
31
-
32
- def construct_classes(classes)
33
- TAILWIND_MERGER.merge([ BASE, SIZES[size], classes ].compact)
34
- end
35
31
  end
@@ -25,17 +25,11 @@ class Essence::Badge < Essence::Essence
25
25
  def initialize(size: :md, kind: :primary, **attributes)
26
26
  @size = size
27
27
  @kind = kind
28
- @attributes = attributes
29
- @attributes[:class] = construct_classes(@attributes[:class])
28
+ super(**attributes)
29
+ @attributes[:class] = merge_classes([ BASE, SIZES[size], KINDS[kind], @attributes[:class]])
30
30
  end
31
31
 
32
32
  def view_template(&)
33
33
  div(**attributes, &)
34
34
  end
35
-
36
- private
37
-
38
- def construct_classes(classes)
39
- TAILWIND_MERGER.merge([ BASE, SIZES[size], KINDS[kind], classes ].compact)
40
- end
41
35
  end
@@ -19,7 +19,7 @@ class Essence::Button < Essence::Essence
19
19
  info: "text-white bg-blue-500 hover:bg-blue-400",
20
20
  dark: "text-white bg-gray-900 hover:bg-gray-800",
21
21
  white: "text-gray-900 bg-white hover:bg-gray-200",
22
- ghost: "text-gray-900 bg-white hover:bg-gray-200 hover:text-gray-800"
22
+ ghost: "text-gray-900 hover:bg-gray-200 hover:text-gray-800"
23
23
  }
24
24
 
25
25
  attr_reader :size
@@ -29,8 +29,8 @@ class Essence::Button < Essence::Essence
29
29
  def initialize(size: :md, kind: :primary, **attributes)
30
30
  @size = size
31
31
  @kind = kind
32
- @attributes = attributes
33
- @attributes[:class] = construct_classes(@attributes[:class])
32
+ super(**attributes)
33
+ @attributes[:class] = merge_classes([ BASE, SIZES[size], KINDS[kind], @attributes[:class]])
34
34
  end
35
35
 
36
36
  def view_template(&)
@@ -42,8 +42,4 @@ class Essence::Button < Essence::Essence
42
42
  def element_tag(...)
43
43
  attributes[:href] ? a(...) : button(...)
44
44
  end
45
-
46
- def construct_classes(classes)
47
- TAILWIND_MERGER.merge([ BASE, SIZES[size], KINDS[kind], classes ].compact)
48
- end
49
45
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Essence::Dialog < Essence::Essence
4
+ BASE = ""
5
+
6
+ attr_reader :attributes
7
+
8
+ def initialize(**attributes)
9
+ super(**attributes)
10
+ @attributes[:class] = merge_classes([ BASE, @attributes[:class]])
11
+ end
12
+
13
+ def view_template(&)
14
+ dialog(**attributes) do
15
+ yield if block_given?
16
+ end
17
+ end
18
+
19
+ def footer(&)
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Essence::Dropdown < Essence::Essence
4
+ BASE = ""
5
+
6
+ attr_reader :attributes
7
+
8
+ def initialize(**attributes)
9
+ super(**attributes)
10
+ @attributes[:class] = merge_classes([ BASE, @attributes[:class]])
11
+ end
12
+
13
+ def view_template(&)
14
+ div(**attributes) do
15
+ yield if block_given?
16
+ end
17
+ end
18
+ end
@@ -6,13 +6,11 @@ class Essence::Essence < Phlex::HTML
6
6
  attr_reader :attributes
7
7
 
8
8
  def initialize(**attributes)
9
- @attributes = attributes
10
- @attributes[:class] = TAILWIND_MERGER.merge([self.class::CLASSES, @attributes[:class]]) if @attributes[:class]
9
+ @attributes = default_attributes.deep_merge(attributes)
11
10
  end
12
11
 
13
12
  private
14
13
 
15
- def default_attributes
16
- {}
17
- end
14
+ def default_attributes = {}
15
+ def merge_classes(*classes) = TAILWIND_MERGER.merge([ *classes ].compact)
18
16
  end
@@ -10,8 +10,8 @@ class Essence::Link < Essence::Essence
10
10
  attr_reader :attributes
11
11
 
12
12
  def initialize(kind: :regular, **attributes)
13
- @attributes = attributes
14
- @attributes[:class] = @attributes[:class] ? TAILWIND_MERGER.merge([ BASE, @attributes[:class] ]) : BASE
13
+ super(**attributes)
14
+ @attributes[:class] = merge_classes([ BASE, @attributes[:class]])
15
15
  end
16
16
 
17
17
  def view_template(&)
@@ -14,8 +14,8 @@ class Essence::Row < Essence::Essence
14
14
 
15
15
  def initialize(kind: :default, **attributes)
16
16
  @kind = kind
17
- @attributes = attributes
18
- @attributes[:class] = @attributes[:class] ? TAILWIND_MERGER.merge([ BASE, KINDS[kind], @attributes[:class] ]) : BASE
17
+ super(**attributes)
18
+ @attributes[:class] = merge_classes([ BASE, KINDS[kind], @attributes[:class]])
19
19
  end
20
20
 
21
21
  def view_template(&)
@@ -1,11 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # A skeleton component is used to show a loading state.
4
+ #
5
+ # ==== Examples
6
+ #
7
+ # render Skeleton.new(class: "w-32 h-6")
8
+ #
9
+ # ==== Documentation
10
+ #
11
+ # https://essence.primevise.com/components/skeleton
12
+ #
3
13
  class Essence::Skeleton < Essence::Essence
4
14
  BASE = "animate-pulse bg-gray-200/55 rounded-xs"
5
15
 
6
16
  def initialize(**attributes)
7
- @attributes = attributes
8
- @attributes[:class] = @attributes[:class] ? TAILWIND_MERGER.merge([ BASE, @attributes[:class] ]) : BASE
17
+ super(**attributes)
18
+ @attributes[:class] = merge_classes([ BASE, @attributes[:class]])
9
19
  end
10
20
 
11
21
  def view_template(&)
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Essence::Tabs < Essence::Essence
4
+ BASE = "rounded-lg overflow-hidden"
5
+ TAB_BASE = "inline-flex items-center justify-center w-fit rounded-xs border border-transparent font-medium transition duration-150 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed hover:opacity-90 text-xs px-3 py-2 gap-1.5 text-gray-900 bg-transparent hover:bg-gray-200 hover:text-gray-800"
6
+ TAB_LIST_BASE = "flex items-center gap-2 py-2 border-b"
7
+ PANEL_BASE = "aria-hidden:hidden p-4"
8
+
9
+ attr_reader :attributes
10
+
11
+ def initialize(**attributes)
12
+ super(**attributes)
13
+ @attributes[:class] = merge_classes([ BASE, @attributes[:class] ])
14
+ end
15
+
16
+ def view_template(&)
17
+ div(**attributes, &)
18
+ end
19
+
20
+ def menu(**mattributes, &)
21
+ mattributes[:class] = merge_classes([ TAB_LIST_BASE, mattributes[:class] ])
22
+
23
+ div(**mattributes, &)
24
+ end
25
+
26
+ def tab(key: :general, **mattributes, &)
27
+ mattributes[:id] = "tab-#{key}"
28
+ mattributes[:class] = merge_classes([ TAB_BASE, mattributes[:class] ])
29
+ mattributes[:data] = {
30
+ essence__tabs_target: "tab",
31
+ essence__tabs_panel_id_param: "panel-#{key}",
32
+ action: "essence--tabs#setActiveTab keydown.left->essence--tabs#previous keydown.right->essence--tabs#next"
33
+ }
34
+
35
+ button(**mattributes, &)
36
+ end
37
+
38
+ def panel(key: :general, **mattributes, &)
39
+ mattributes[:id] = "panel-#{key}"
40
+ mattributes[:class] = merge_classes([ PANEL_BASE, mattributes[:class] ])
41
+ mattributes[:data] = {
42
+ essence__tabs_target: "panel"
43
+ }
44
+
45
+ div(**mattributes, &)
46
+ end
47
+
48
+ private
49
+
50
+ def default_attributes
51
+ {
52
+ data: {
53
+ controller: "essence--tabs",
54
+ essence__tabs_active_value: "panel-general"
55
+ }
56
+ }
57
+ end
58
+ end
@@ -0,0 +1,11 @@
1
+ module Essence
2
+ class Configuration
3
+ attr_accessor :phlex_components_path
4
+ attr_accessor :stimulus_controller_path
5
+
6
+ def initialize
7
+ @phlex_components_path = "app/components"
8
+ @stimulus_controller_path = "app/javascript/controllers/essence"
9
+ end
10
+ end
11
+ end
@@ -1,3 +1,3 @@
1
1
  module Essence
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/essence.rb CHANGED
@@ -2,8 +2,12 @@
2
2
 
3
3
  require "tailwind_merge"
4
4
 
5
+ require_relative "essence/configuration"
6
+
5
7
  module Essence
6
8
  # Autoloading
9
+ # Components
10
+ autoload :Accordion, "essence/components/accordion"
7
11
  autoload :Avatar, "essence/components/avatar"
8
12
  autoload :Badge, "essence/components/badge"
9
13
  autoload :Button, "essence/components/button"
@@ -12,36 +16,83 @@ module Essence
12
16
  autoload :Row, "essence/components/row"
13
17
  autoload :Skeleton, "essence/components/skeleton"
14
18
 
19
+ # CLI
15
20
  autoload :CLI, "essence/cli"
16
21
 
17
- # Components
18
- # Class names and classes are separated to avoid loading in Phlex into the CLI tooling
19
-
20
- def self.component_class_names
21
- @component_class_names ||= {
22
- essence: "Essence::Essence",
23
- avatar: "Essence::Avatar",
24
- badge: "Essence::Badge",
25
- button: "Essence::Button",
26
- link: "Essence::Link",
27
- row: "Essence::Row",
28
- skeleton: "Essence::Skeleton",
29
- }
30
- end
22
+ class << self
23
+ def root_path
24
+ File.dirname(__dir__)
25
+ end
31
26
 
32
- def self.component_classes
33
- @components_classes ||= {
34
- essence: ::Essence::Essence,
35
- avatar: ::Essence::Avatar,
36
- badge: ::Essence::Badge,
37
- button: ::Essence::Button,
38
- link: ::Essence::Link,
39
- row: ::Essence::Row,
40
- skeleton: ::Essence::Skeleton,
41
- }
42
- end
27
+ # CONFIGURATION
28
+ def configuration
29
+ @configuration ||= Configuration.new
30
+ end
31
+
32
+ def configure
33
+ yield configuration
34
+ end
35
+
36
+ # COMPONENTS
37
+ def components
38
+ @components ||= {
39
+ accordion: {
40
+ name: "Accordion",
41
+ class_name: "Essence::Accordion",
42
+ stimulus: false
43
+ },
44
+ avatar: {
45
+ name: "Avatar",
46
+ class_name: "Essence::Avatar",
47
+ stimulus: false
48
+ },
49
+ badge: {
50
+ name: "Badge",
51
+ class_name: "Essence::Badge",
52
+ stimulus: false
53
+ },
54
+ button: {
55
+ name: "Button",
56
+ class_name: "Essence::Button",
57
+ stimulus: false
58
+ },
59
+ link: {
60
+ name: "Link",
61
+ class_name: "Essence::Link",
62
+ stimulus: false
63
+ },
64
+ row: {
65
+ name: "Row",
66
+ class_name: "Essence::Row",
67
+ stimulus: false
68
+ },
69
+ skeleton: {
70
+ name: "Skeleton",
71
+ class_name: "Essence::Skeleton",
72
+ stimulus: false
73
+ },
74
+ tabs: {
75
+ name: "Tabs",
76
+ class_name: "Essence::Tabs",
77
+ stimulus: true
78
+ }
79
+ }
80
+ end
81
+
82
+ def component_keys
83
+ @component_keys ||= components.keys
84
+ end
85
+
86
+ def component_names
87
+ @component_names ||= components.transform_values { |v| v[:name] }
88
+ end
89
+
90
+ def component_class_names
91
+ @component_class_names ||= components.transform_values { |v| v[:class_name] }
92
+ end
43
93
 
44
- def self.component_names
45
- @component_names ||= component_class_names.keys
94
+ def component_classes
95
+ @component_classes ||= component_class_names.transform_values { |v| Object.const_get(v) }
96
+ end
46
97
  end
47
98
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: essence
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elvinas Predkelis
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2024-12-22 00:00:00.000000000 Z
12
+ date: 2025-01-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: dry-cli
@@ -74,13 +74,18 @@ files:
74
74
  - lib/essence/cli/add.rb
75
75
  - lib/essence/cli/install.rb
76
76
  - lib/essence/cli/version.rb
77
+ - lib/essence/components/accordion.rb
77
78
  - lib/essence/components/avatar.rb
78
79
  - lib/essence/components/badge.rb
79
80
  - lib/essence/components/button.rb
81
+ - lib/essence/components/dialog.rb
82
+ - lib/essence/components/dropdown.rb
80
83
  - lib/essence/components/essence.rb
81
84
  - lib/essence/components/link.rb
82
85
  - lib/essence/components/row.rb
83
86
  - lib/essence/components/skeleton.rb
87
+ - lib/essence/components/tabs.rb
88
+ - lib/essence/configuration.rb
84
89
  - lib/essence/version.rb
85
90
  homepage: https://rubygems.org/gems/essence
86
91
  licenses: