essence 0.1.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a9516a2911b410deb58ca4b9ba2afbf083752314b0bb6df0018c81a4615f14d
4
- data.tar.gz: 51074c18359021237cc4588b64a858aed0464746d5b9d0f0513319e722b73828
3
+ metadata.gz: b698fdfbf94b34b4afa01e1c6f38a2e9ac2feca00f34166c0acead4c4e6c8e40
4
+ data.tar.gz: b11e693d29dbc9bd6763725692570bffb8879cafb32967cc1c34a2fbc5c65881
5
5
  SHA512:
6
- metadata.gz: a94fccdf29ea63f7fd807b786f8bd477ac44feb623a19bae66814412d6c170536b15ec46f8f02266c5bf6afbc0db61f2c30e95f2b58e5a6dbb3288a807af18ac
7
- data.tar.gz: 8e49f1011e3ddbecf3b37f3f5a0bd257b94061eab3053c8f06f616f3a60cd5f179688f9deacda83eb6ccb9129c48a0c47c6b8607fe5ca80c36e9b22e379c5dec
6
+ metadata.gz: b95a0636aca009728061fc524f93bfeacf2728aa846e7e6ff7afa8918ba99ce1a47ba80ef8bc44863d982c0cb8cc1ef760f61f9c367b9cddd9beda463de5798c
7
+ data.tar.gz: 371fb23359faf1f9e5835394c2fea1952813d7f43bf0f008704b641dca2d50faa2463c371869d1511a8625a22b9416ac8d2c3b59f09ceae36ca1c1e6fc865d29
data/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # Essence
2
+
3
+ A simple, ergonomic and performant component library for Ruby applications.
4
+
5
+ <a href="https://rubygems.org/gems/essence">
6
+ <img alt="Essence GEM Version" src="https://img.shields.io/gem/v/essence?color=10b981&include_prereleases&logo=ruby&logoColor=f43f5e">
7
+ </a>
8
+
9
+ <a href="https://rubygems.org/gems/essence">
10
+ <img alt="Essence GEM Version" src="https://img.shields.io/gem/dt/essence?color=10b981&include_prereleases&logo=ruby&logoColor=f43f5e">
11
+ </a>
12
+
13
+ ---
14
+
15
+ ### Features
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
21
+
22
+ ---
23
+
24
+ ## Installation
25
+
26
+ #### Add gem
27
+
28
+ Simply add the gem to your Gemfile by running the following command
29
+
30
+ ```bash
31
+ bundle add essence
32
+ ```
33
+
34
+ #### Install Essence
35
+
36
+ Run the installation command and we'll take care of the rest
37
+
38
+ ```bash
39
+ bundle exec essence install
40
+ ```
41
+
42
+ More information on about the installation can be found in the [documentation](https://essence.primevise.com/installation)
43
+
44
+ ## Who uses Essence?
45
+
46
+ - [Mintis](https://mintis.app)
47
+ - [Hansa](https://hansahq.com)
48
+ - [Release Server](https://releaseserver.com)
49
+ - [College Life Work](https://work.collegelife.co)
50
+
51
+ Do you use Essence in your project? Let us know!
52
+
53
+ ## Licence
54
+
55
+ MIT
data/exe/essence ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require_relative "../lib/essence"
6
+
7
+ Essence::CLI.call
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Essence
4
+ module CLI
5
+ class Add < Dry::CLI::Command
6
+ desc "Add an Essence component to your project"
7
+ argument :component_name, required: true, desc: "Component name"
8
+ example Essence.component_names
9
+
10
+ def call(*args)
11
+ component_name = args[0][:component_name]
12
+
13
+ return puts "> #{component_name}: component unsupported" unless Essence.component_names.include?(component_name.to_sym)
14
+
15
+ Essence::CLI::Commands.copy_component(component_name:)
16
+ Essence::CLI::Commands.replace_component_contents(component_name:)
17
+ Essence::CLI::Commands.replace_component_contents(
18
+ component_name:,
19
+ from: Essence::CLI::Commands::COMPONENT_DEFINITION_SUFFIX,
20
+ to: Essence::CLI::Commands::PHLEX_COMPONENT_DEFINITION_SUFFIX
21
+ )
22
+
23
+ puts "> Successfully added #{component_name} component to #{Essence::CLI::Commands::DESTINATION_DIR.join("#{component_name}.rb")}"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Essence
4
+ module CLI
5
+ class Install < Dry::CLI::Command
6
+ BASE_COMPONENT_NAME = "essence"
7
+ BASE_DEFINITION_PREFIX = "class Essence::Essence"
8
+ PHLEX_BASE_DEFINITION_PREFIX = "class Components::Essence"
9
+
10
+ desc "Install Essence to your project"
11
+ def call(*)
12
+ puts "> Installing Essence..."
13
+ puts "> Copying base component to your project"
14
+ Essence::CLI::Commands.copy_component(component_name: BASE_COMPONENT_NAME)
15
+ Essence::CLI::Commands.replace_component_contents(
16
+ component_name: BASE_COMPONENT_NAME,
17
+ from: BASE_DEFINITION_PREFIX,
18
+ to: PHLEX_BASE_DEFINITION_PREFIX
19
+ )
20
+ # Essence::CLI::Commands.rename_component_file(
21
+ # from: Essence::CLI::Commands::DESTINATION_DIR.join("#{BASE_COMPONENT_NAME}.rb"),
22
+ # to: Essence::CLI::Commands::DESTINATION_DIR.join("essence.rb")
23
+ # )
24
+ puts "> Essence has been successfully installed!"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Essence
4
+ module CLI
5
+ class Version < Dry::CLI::Command
6
+ desc "Print Essence version"
7
+
8
+ def call(*)
9
+ puts Essence::VERSION
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/cli"
4
+
5
+ # CLI Commands
6
+ require_relative "cli/add"
7
+ require_relative "cli/install"
8
+ require_relative "cli/version"
9
+
10
+ module Essence
11
+ module CLI
12
+ def self.call(*args)
13
+ Dry::CLI.new(Commands).call
14
+ end
15
+
16
+ module Commands
17
+ extend Dry::CLI::Registry
18
+
19
+ # Constants
20
+ COMPONENTS_DIR = Pathname.new(File.expand_path("components", __dir__))
21
+ DESTINATION_DIR = Pathname.new(File.expand_path(Dir.pwd)).join("app/components")
22
+ COMPONENT_DEFINITION_PREFIX = "class Essence::"
23
+ COMPONENT_DEFINITION_SUFFIX = "< Essence::Essence"
24
+ PHLEX_COMPONENT_DEFINITION_PREFIX = "class Components::"
25
+ PHLEX_COMPONENT_DEFINITION_SUFFIX = "< Components::Essence"
26
+
27
+ # Registering commands
28
+ register "add", Add, aliases: ["a", "generate", "g"]
29
+ register "install", Install, aliases: ["i"]
30
+ register "version", Version, aliases: ["v", "-v", "--version"]
31
+
32
+ private
33
+
34
+ # UTILITIES
35
+ def self.copy_component(component_name:)
36
+ source_path = COMPONENTS_DIR.join("#{component_name}.rb")
37
+ destination_path = DESTINATION_DIR.join("#{component_name}.rb")
38
+
39
+ FileUtils.mkdir_p(DESTINATION_DIR)
40
+ FileUtils.copy(source_path, destination_path)
41
+ end
42
+
43
+ def self.replace_component_contents(
44
+ component_name:,
45
+ from: COMPONENT_DEFINITION_PREFIX,
46
+ to: PHLEX_COMPONENT_DEFINITION_PREFIX
47
+ )
48
+ component_file = DESTINATION_DIR.join("#{component_name}.rb")
49
+ return unless File.exist?(component_file)
50
+
51
+ replaced_content = File.read(component_file).gsub(from, to)
52
+ File.write(component_file, replaced_content)
53
+ end
54
+
55
+ def self.rename_component_file(from:, to:)
56
+ return if from.nil? || to.nil?
57
+ return unless File.exist?(from)
58
+
59
+ FileUtils.mv(from, to)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Essence::Button < Essence::Essence
4
+ 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"
5
+ SIZES = {
6
+ none: "",
7
+ xs: "text-[0.6rem] px-2 py-1.5 gap-1",
8
+ sm: "text-xs px-3 py-2 gap-1.5",
9
+ md: "text-sm px-4 py-2 gap-2",
10
+ lg: "text-base px-6 py-2.5 gap-2.5",
11
+ xl: "text-base px-8 py-3 gap-3"
12
+ }
13
+ KINDS = {
14
+ primary: "text-white bg-indigo-500 hover:bg-indigo-500",
15
+ secondary: "text-gray-700 bg-gray-100 hover:bg-gray-200",
16
+ critical: "text-white bg-rose-500 hover:bg-rose-400",
17
+ warning: "text-white bg-amber-500 hover:bg-amber-400",
18
+ success: "text-white bg-emerald-500 hover:bg-emerald-400",
19
+ info: "text-white bg-blue-500 hover:bg-blue-400",
20
+ dark: "text-white bg-gray-900 hover:bg-gray-800",
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"
23
+ }
24
+
25
+ attr_reader :size
26
+ attr_reader :kind
27
+ attr_reader :attributes
28
+
29
+ def initialize(size: :md, kind: :primary, **attributes)
30
+ @size = size
31
+ @kind = kind
32
+ @attributes = attributes
33
+ @attributes[:class] = construct_classes(@attributes[:class])
34
+ end
35
+
36
+ def view_template(&)
37
+ element_tag(**attributes, &)
38
+ end
39
+
40
+ private
41
+
42
+ def element_tag(...)
43
+ attributes[:href] ? a(...) : button(...)
44
+ end
45
+
46
+ def construct_classes(classes)
47
+ TAILWIND_MERGER.merge([ BASE, SIZES[size], KINDS[kind], classes ].compact)
48
+ end
49
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Essence::Avatar < Essence::Essence
4
+ BASE = "border border-transparent rounded-full bg-gray-100 aspect-square inline-flex items-center justify-center font-medium text-gray-700"
5
+ SIZES = {
6
+ sm: "size-6 text-xs",
7
+ md: "size-8 text-sm",
8
+ lg: "size-12 text-base"
9
+ }
10
+
11
+ attr_reader :attributes
12
+ attr_reader :size
13
+
14
+ def initialize(size: :md, **attributes)
15
+ @size = size
16
+ @attributes = attributes
17
+ @attributes[:class] = construct_classes(@attributes[:class])
18
+ end
19
+
20
+ def view_template(&)
21
+ div(**attributes, &)
22
+ end
23
+
24
+ def fallback(**attrs, &)
25
+ span(**attrs, &)
26
+ end
27
+
28
+ def construct_classes(classes)
29
+ TAILWIND_MERGER.merge([ BASE, SIZES[size], classes ].compact)
30
+ end
31
+ end
@@ -1,27 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Essence::Button < Essence::Component
4
- BASE = "inline-flex items-center rounded-xs border border-transparent font-medium transition duration-150 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed hover:opacity-90"
5
-
3
+ class Essence::Badge < Essence::Essence
4
+ BASE = "inline-flex items-center justify-center w-fit rounded-full border border-transparent font-medium transition duration-150 hover:opacity-90"
6
5
  SIZES = {
7
6
  none: "",
8
- xs: "text-[0.6rem] px-2 py-1.5 gap-1",
9
- sm: "text-xs px-3 py-2 gap-1.5",
10
- md: "text-sm px-4 py-2 gap-2",
11
- lg: "text-base px-6 py-2.5 gap-2.5",
12
- xl: "text-base px-8 py-3 gap-3"
7
+ sm: "text-[0.65rem] px-2 py-0.5 gap-1",
8
+ md: "text-xs px-2.5 py-1 gap-2",
9
+ lg: "text-sm px-4 py-1.5 gap-2"
13
10
  }
14
-
15
11
  KINDS = {
16
- primary: "text-white bg-indigo-500 hover:bg-indigo-500",
17
- secondary: "text-gray-700 bg-gray-100 hover:bg-gray-200",
18
- critical: "text-white bg-rose-500 hover:bg-rose-400",
19
- warning: "text-white bg-amber-500 hover:bg-amber-400",
20
- success: "text-white bg-emerald-500 hover:bg-emerald-400",
21
- info: "text-white bg-blue-500 hover:bg-blue-400",
22
- dark: "text-white bg-gray-900 hover:bg-gray-800",
23
- white: "text-gray-900 bg-white hover:bg-gray-200",
24
- ghost: "text-gray-900 bg-white hover:bg-gray-200 hover:text-gray-800"
12
+ primary: "text-gray-900 border-gray-200",
13
+ success: "text-white bg-emerald-500",
14
+ critical: "text-white bg-rose-500",
15
+ warning: "text-white bg-amber-500",
16
+ info: "text-white bg-blue-500",
17
+ dark: "text-white bg-gray-900",
18
+ white: "text-gray-900 bg-white"
25
19
  }
26
20
 
27
21
  attr_reader :size
@@ -36,16 +30,13 @@ class Essence::Button < Essence::Component
36
30
  end
37
31
 
38
32
  def view_template(&)
39
- element_tag(**attributes, &)
33
+ div(**attributes, &)
40
34
  end
41
35
 
42
36
  private
43
37
 
44
- def element_tag(...)
45
- attributes[:href] ? a(...) : button(...)
46
- end
47
-
48
38
  def construct_classes(classes)
49
39
  TAILWIND_MERGER.merge([ BASE, SIZES[size], KINDS[kind], classes ].compact)
50
40
  end
41
+
51
42
  end
@@ -1,4 +1,6 @@
1
- class Essence::Component < Phlex::HTML
1
+ class Essence::Essence < Phlex::HTML
2
+ extend Phlex::Kit
3
+
2
4
  TAILWIND_MERGER = ::TailwindMerge::Merger.new.freeze unless defined?(TAILWIND_MERGER)
3
5
 
4
6
  attr_reader :attributes
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Essence::Link < Essence::Component
4
- CLASS = "inline-flex items-center gap-1 font-medium text-gray-900 border-b-2 hover:border-gray-900 transition-colors"
3
+ class Essence::Link < Essence::Essence
4
+ BASE = "inline-flex w-fit items-center gap-1 font-medium text-gray-900 border-b-2 hover:border-gray-900 transition-colors"
5
5
  KINDS = {
6
6
  regular: "border-transparent",
7
7
  underline: "border-gray-200"
@@ -11,7 +11,7 @@ class Essence::Link < Essence::Component
11
11
 
12
12
  def initialize(kind: :regular, **attributes)
13
13
  @attributes = attributes
14
- @attributes[:class] = @attributes[:class] ? TAILWIND_MERGER.merge([ CLASS, @attributes[:class] ]) : CLASS
14
+ @attributes[:class] = @attributes[:class] ? TAILWIND_MERGER.merge([ BASE, @attributes[:class] ]) : BASE
15
15
  end
16
16
 
17
17
  def view_template(&)
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Essence::Row < Essence::Component
4
- CLASS = "flex gap-4"
5
-
3
+ class Essence::Row < Essence::Essence
4
+ BASE = "flex gap-4"
6
5
  KINDS = {
7
6
  default: "flex-col md:flex-row md:items-center md:justify-between",
8
7
  center: "flex-col md:flex-row md:items-center md:justify-center",
@@ -16,7 +15,7 @@ class Essence::Row < Essence::Component
16
15
  def initialize(kind: :default, **attributes)
17
16
  @kind = kind
18
17
  @attributes = attributes
19
- @attributes[:class] = @attributes[:class] ? TAILWIND_MERGER.merge([ CLASS, KINDS[kind], @attributes[:class] ]) : CLASS
18
+ @attributes[:class] = @attributes[:class] ? TAILWIND_MERGER.merge([ BASE, KINDS[kind], @attributes[:class] ]) : BASE
20
19
  end
21
20
 
22
21
  def view_template(&)
@@ -24,6 +23,6 @@ class Essence::Row < Essence::Component
24
23
  end
25
24
 
26
25
  def item(**attrs, &)
27
- div(class: TAILWIND_MERGER.merge([ "flex items-center gap-2 flex-wrap", iattrs[:class] ]), **attrs, &)
26
+ div(class: TAILWIND_MERGER.merge([ "flex items-center gap-2 flex-wrap", attrs[:class] ]), **attrs, &)
28
27
  end
29
28
  end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Essence::Skeleton < Essence::Component
4
- CLASSES = "animate-pulse bg-gray-200/55 rounded-xs"
3
+ class Essence::Skeleton < Essence::Essence
4
+ BASE = "animate-pulse bg-gray-200/55 rounded-xs"
5
5
 
6
6
  def initialize(**attributes)
7
7
  @attributes = attributes
8
- @attributes[:class] = @attributes[:class] ? TAILWIND_MERGER.merge([ CLASSES, @attributes[:class] ]) : CLASSES
8
+ @attributes[:class] = @attributes[:class] ? TAILWIND_MERGER.merge([ BASE, @attributes[:class] ]) : BASE
9
9
  end
10
10
 
11
11
  def view_template(&)
@@ -1,3 +1,3 @@
1
1
  module Essence
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.1"
3
3
  end
data/lib/essence.rb CHANGED
@@ -1,11 +1,46 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "tailwind_merge"
2
4
 
3
5
  module Essence
4
6
  # Autoloading
5
- autoload :Component, "essence/component"
7
+ autoload :Component, "essence/components/component"
6
8
 
7
9
  autoload :Button, "essence/components/button"
8
10
  autoload :Link, "essence/components/link"
9
11
  autoload :Skeleton, "essence/components/skeleton"
10
12
  autoload :Row, "essence/components/row"
13
+
14
+ autoload :CLI, "essence/cli"
15
+
16
+ # Components
17
+ # Class names and classes are separated to avoid loading in Phlex into the CLI tooling
18
+
19
+ def self.component_class_names
20
+ @component_class_names ||= {
21
+ essence: "Essence::Essence",
22
+ avataro: "Essence::Avatar",
23
+ badge: "Essence::Badge",
24
+ button: "Essence::Button",
25
+ link: "Essence::Link",
26
+ skeleton: "Essence::Skeleton",
27
+ row: "Essence::Row",
28
+ }
29
+ end
30
+
31
+ def self.component_classes
32
+ @components_classes ||= {
33
+ essence: ::Essence::Essence,
34
+ avatar: ::Essence::Avatar,
35
+ badge: ::Essence::Badge,
36
+ button: ::Essence::Button,
37
+ link: ::Essence::Link,
38
+ skeleton: ::Essence::Skeleton,
39
+ row: ::Essence::Row,
40
+ }
41
+ end
42
+
43
+ def self.component_names
44
+ @component_names ||= component_class_names.keys
45
+ end
11
46
  end
metadata CHANGED
@@ -1,16 +1,36 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: essence
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elvinas Predkelis
8
8
  - Primevise
9
9
  autorequire:
10
- bindir: bin
10
+ bindir: exe
11
11
  cert_chain: []
12
- date: 2024-12-15 00:00:00.000000000 Z
12
+ date: 2024-12-22 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: dry-cli
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0.7'
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: '2'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ version: '0.7'
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: '2'
14
34
  - !ruby/object:Gem::Dependency
15
35
  name: phlex
16
36
  requirement: !ruby/object:Gem::Requirement
@@ -42,13 +62,22 @@ dependencies:
42
62
  description: Component library for Ruby applications using Phlex
43
63
  email:
44
64
  - info@primevise.com
45
- executables: []
65
+ executables:
66
+ - essence
46
67
  extensions: []
47
68
  extra_rdoc_files: []
48
69
  files:
70
+ - README.md
71
+ - exe/essence
49
72
  - lib/essence.rb
50
- - lib/essence/component.rb
73
+ - lib/essence/cli.rb
74
+ - lib/essence/cli/add.rb
75
+ - lib/essence/cli/install.rb
76
+ - lib/essence/cli/version.rb
77
+ - lib/essence/components/avatar.rb
78
+ - lib/essence/components/badge.rb
51
79
  - lib/essence/components/button.rb
80
+ - lib/essence/components/essence.rb
52
81
  - lib/essence/components/link.rb
53
82
  - lib/essence/components/row.rb
54
83
  - lib/essence/components/skeleton.rb