Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90ae597a66 | ||
|
|
885e2c16fe | ||
|
|
6156675fb9 | ||
|
|
ad6973d069 | ||
|
|
231da5b0b8 | ||
|
|
945802cb23 | ||
|
|
57e77b7cd1 | ||
|
|
74bea16b2f | ||
|
|
9a9445ca01 | ||
|
|
c7b2980a30 | ||
|
|
08f4e469e3 | ||
|
|
58c4744aa7 | ||
|
|
39c7346e0a | ||
|
|
97cee0127d | ||
|
|
d03b00e30a | ||
|
|
c200d5743a | ||
|
|
131b1e13f4 | ||
|
|
a1d3edcb82 | ||
|
|
3914461f55 | ||
|
|
5dc6e5ca38 | ||
|
|
f0004d112b | ||
|
|
c747c30063 | ||
|
|
ad225404f4 | ||
|
|
d9fe873bb5 | ||
|
|
0193e67f72 | ||
|
|
3c34ce5f71 | ||
|
|
8ebf7eba9c | ||
|
|
848b95113a | ||
|
|
d4c304f725 | ||
|
|
444ff0d672 | ||
|
|
52e2ee4a70 | ||
|
|
bf49a94642 | ||
|
|
3a2e41fa69 | ||
|
|
36e8d1fac9 | ||
|
|
dcc13811e8 | ||
|
|
93972f8af8 | ||
|
|
65a99475e8 | ||
|
|
aa489ccd31 | ||
|
|
d90a765cc7 | ||
|
|
550373f48e | ||
|
|
636725681a | ||
|
|
14de42933e | ||
|
|
2ba910386f | ||
|
|
a7c5d53f0a | ||
|
|
59f0da9caa | ||
|
|
4d5c58316c | ||
|
|
bae21e5b2e | ||
|
|
18bc462ad0 | ||
|
|
964cd76178 | ||
|
|
9ba77d490a | ||
|
|
3dddd20dcb | ||
|
|
8c7c3a545d | ||
|
|
4068c556df | ||
|
|
2e273e0d6c | ||
|
|
6dee34b1a7 | ||
|
|
5ce5f6e10d | ||
|
|
298a4e3310 | ||
|
|
db28b2ad2c | ||
|
|
d58b3e14a2 | ||
|
|
c476a56661 | ||
|
|
db210317a3 | ||
|
|
79804619d3 | ||
|
|
76f7e8b9d7 | ||
|
|
1c7300cdf1 | ||
|
|
9b2cb7cc92 | ||
|
|
5022c01468 | ||
|
|
60fb6c5a3b | ||
|
|
6889b51ab6 | ||
|
|
a7e09b5e16 | ||
|
|
0746a7a2c4 | ||
|
|
f5380093ca | ||
|
|
dd4691c650 | ||
|
|
55db159560 | ||
|
|
dcdea93687 | ||
|
|
54b5db9480 | ||
|
|
aa84d79e93 | ||
|
|
9bc28083fd | ||
|
|
cb03b507b3 | ||
|
|
9ffa5088db | ||
|
|
e7dcc93706 | ||
|
|
ad3ae4547c | ||
|
|
dce7797bba | ||
|
|
7c0d666b0a | ||
|
|
c5a2bcdcbf | ||
|
|
85a242bf34 | ||
|
|
2117840e40 | ||
|
|
9fec1ce5a5 | ||
|
|
88ef237566 | ||
|
|
cb84409701 | ||
|
|
69330aa0fe | ||
|
|
76fab9d179 | ||
|
|
feed398b6d | ||
|
|
8422e695ea | ||
|
|
7fd2548c9c | ||
|
|
dc8407ad35 | ||
|
|
4379ba8ce7 | ||
|
|
eaeb493d6b | ||
|
|
9de5f9508f | ||
|
|
93cbaa673f | ||
|
|
646ec5c901 | ||
|
|
beecc84d14 | ||
|
|
ab0df706bb | ||
|
|
5edd0142af | ||
|
|
3c49650bc3 | ||
|
|
f286ab4b3c | ||
|
|
7dc9a9daa7 | ||
|
|
7f353e9169 | ||
|
|
33757a96e8 | ||
|
|
47a6ba4632 | ||
|
|
507aa096dd | ||
|
|
c28af2a722 | ||
|
|
1d01db34ff | ||
|
|
6d70e03a9e | ||
|
|
d69eb04b11 | ||
|
|
f891c26ee2 | ||
|
|
12ef593bd7 | ||
|
|
3f17ec4abc | ||
|
|
f0010494fa | ||
|
|
5c17cc660d | ||
|
|
41ff7485d5 | ||
|
|
fbdb5cd49a | ||
|
|
c920f84e13 | ||
|
|
84d85ea28e | ||
|
|
dd060e8b42 | ||
|
|
786babc988 | ||
|
|
9739ab3b46 | ||
|
|
ab31ddda40 | ||
|
|
08d65c4410 | ||
|
|
f7cd98ae4e | ||
|
|
419f8b562e | ||
|
|
927ba55dff | ||
|
|
28aea99a3b | ||
|
|
e7c6c11342 | ||
|
|
d2d915a8ea | ||
|
|
6b8bcfbc1a | ||
|
|
31be26e167 | ||
|
|
9c788a56cd | ||
|
|
5bc1734cb6 | ||
|
|
aba27cf9d3 | ||
|
|
a098db62c3 | ||
|
|
c4886127a6 | ||
|
|
343d671575 | ||
|
|
06a0411f84 | ||
|
|
ffe3d45017 | ||
|
|
16005be3e6 | ||
|
|
005adb10ce | ||
|
|
0a7d9e6a25 | ||
|
|
0edfb29851 | ||
|
|
52f567fded | ||
|
|
116b1a3be8 | ||
|
|
84cc6fcf60 | ||
|
|
1f4266ec95 | ||
|
|
c85b3ccd24 | ||
|
|
7687943ecf | ||
|
|
587d25bb40 | ||
|
|
5561d37ce8 | ||
|
|
fffbea22af | ||
|
|
934d45617a | ||
|
|
ccb6f2208c | ||
|
|
d9e4383b22 | ||
|
|
cbd8458776 | ||
|
|
3352b66a26 | ||
|
|
9b5ceed501 | ||
|
|
3687a0807d | ||
|
|
bda9966330 | ||
|
|
f0be7b6af6 | ||
|
|
3b0f0ddf1e | ||
|
|
85526b45dd | ||
|
|
a6a7aeb97f | ||
|
|
edf54d3b72 | ||
|
|
7a48102df4 | ||
|
|
a16d03d5a6 | ||
|
|
8410df4fa9 | ||
|
|
295fcf8701 | ||
|
|
ba4f1c9db7 | ||
|
|
bde5c93740 | ||
|
|
2421e4806a | ||
|
|
27a9cf3d58 | ||
|
|
cddbb1c876 | ||
|
|
2ab9d2f450 | ||
|
|
750d66c4ae | ||
|
|
844c01dc75 | ||
|
|
154082e6bd | ||
|
|
5d90858fa3 | ||
|
|
0ae505fd32 | ||
|
|
7b0c6ebe66 | ||
|
|
591083435d | ||
|
|
d23959a9b5 | ||
|
|
1799768389 | ||
|
|
250547f329 | ||
|
|
4f52c445fc | ||
|
|
0c70890258 | ||
|
|
bc656de886 | ||
|
|
fb6e6f6f13 | ||
|
|
a0d79ff9b1 | ||
|
|
f5dfd8726a | ||
|
|
0095cc8d37 | ||
|
|
16fcc21346 | ||
|
|
f5e4f14159 | ||
|
|
0c1d47ef10 | ||
|
|
2d82e85491 | ||
|
|
87e9c79e43 | ||
|
|
c3042d5aa4 |
@@ -19,6 +19,16 @@
|
||||
"group": "test",
|
||||
"args": ["test"]
|
||||
},
|
||||
{
|
||||
"label": "Run Tests Common Typescript",
|
||||
"type": "shell",
|
||||
"command": "yarn",
|
||||
"group": "test",
|
||||
"args": ["test"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/common-typescript"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Run DevServer CE",
|
||||
"group": "build",
|
||||
@@ -107,6 +117,15 @@
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/webapp/packages"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Run Ui Kit Preview",
|
||||
"type": "shell",
|
||||
"command": "yarn",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/common-react/@dbeaver/ui-kit"
|
||||
},
|
||||
"args": ["docs"]
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
|
||||
@@ -7,7 +7,7 @@ CloudBeaver is a web server that provides a rich web interface. The server itsel
|
||||
It is free to use and open-source (licensed under [Apache 2](https://github.com/dbeaver/cloudbeaver/blob/devel/LICENSE) license).
|
||||
See our [WIKI](https://github.com/dbeaver/cloudbeaver/wiki) for more details.
|
||||
|
||||
<img src="https://github.com/dbeaver/cloudbeaver/wiki/images/connection-creation-demo.png" width="400"/>
|
||||
<a><img src="https://github.com/dbeaver/cloudbeaver/wiki/images/connection-creation-demo.png" width="400"/></a>
|
||||
<img src="https://github.com/dbeaver/cloudbeaver/wiki/images/gis-demo.png" width="400"/>
|
||||
<img src="https://github.com/dbeaver/cloudbeaver/wiki/images/data-transfer-demo.png" width="400"/>
|
||||
<img src="https://github.com/dbeaver/cloudbeaver/wiki/images/sql-editor-demo.png" width="400"/>
|
||||
@@ -25,62 +25,56 @@ You can see a live demo of CloudBeaver here: https://demo.cloudbeaver.io
|
||||
|
||||
## Changelog
|
||||
|
||||
### 25.0.3 2025-04-21
|
||||
- Administration: log records now capture create, update, and delete actions for users, teams, and connections for improved tracking and transparency;
|
||||
- SQL Editor: auto-completion has been improved for aliases and camelCase entities;
|
||||
- Users DDL in Oracle is displayed in metadata editor on corresponding tab for users with Oracle administration permissions;
|
||||
- Different bug fixes and enhancements have been made.
|
||||
### 25.1.3 2025-07-21
|
||||
- A password confirmation field has been added for administrators in the Easy Config section to help prevent accidental misconfigurations;
|
||||
- Added column descriptions in the Data Editor to provide more metadata context. You can disable this in Preferences > Data Viewer;
|
||||
- Added the option to display tabs across multiple rows, allowing you to see all tabs without scrolling. You can enable this in Preferences > Interface;
|
||||
- Changed the default engine used for autocompletion in the SQL Editor. This Semantic engine offers improved suggestions for database objects, keywords, and functions. You can switch back to the Legacy engine in Preferences -> SQL Editor;
|
||||
- Clickhouse: fixed the presentation of tuples and map data types in the data editor.
|
||||
|
||||
### 25.1.2 2025-07-07
|
||||
- The CloudBeaver default theme matches the device theme by default now. You can change this behavior in user preferences under the Theme section;
|
||||
- Added a button “Clear” to the Output panel;
|
||||
- Changed the data transfer mechanism to avoid intermediate file creation. The parameter dataExportFileSizeLimit was removed from the server configuration as deprecated;
|
||||
- PostgresSQL: fixed misplaced comment for table DDL generation.
|
||||
|
||||
### 25.0.2 2025-04-07
|
||||
- Data Editor: improved table rendering to scale column width depending on the content.
|
||||
- Improved Navigation tree performance: lost connection does not lead to the application freezing anymore.
|
||||
- Different bug fixes and enhancements have been made.
|
||||
### 25.1.1 2025-06-23
|
||||
### Changes since 25.1.0:
|
||||
- Added a search panel for SQL Editor and Value panel: press Ctrl+F to open a panel that allows searching and replacing by keyword or regular expression.
|
||||
- Added a new welcome screen for a freshly opened application. This screen contains shortcuts to create a new connection, open SQL editor or documentation.
|
||||
- Databend database support has been added.
|
||||
|
||||
### 25.0.1 2025-03-24
|
||||
- Improved performance of the export/import functionality by optimizing disk memory consumption;
|
||||
- Enhanced initial configuration on stage security: if the initial setup time exceeds 1 hour, the server must be restarted.
|
||||
|
||||
### 25.0 2025-03-03
|
||||
### Changes since 24.3.0:
|
||||
- General:
|
||||
- Added transaction log viewing for connections with manual commit mode. This allows users to see all modifying statements before committing;
|
||||
- Added an ability for all editors to reconnect if a connection has been lost;
|
||||
- Tooltips for metadata objects and SQL Editor tabs now include additional details about catalogs, schemas, and connections;
|
||||
- Added Ctrl + Shift + S (Cmd + Shift + S on Mac) shortcut for the "Save As Script" action;
|
||||
- Updated list of available shortcuts for macOS.
|
||||
### 25.1.0 2025-06-02
|
||||
### Changes since 25.0.0:
|
||||
- Important:
|
||||
- Connection templates were removed from the application. You can use the Connection Editor to create new connections.
|
||||
- Administration:
|
||||
- Added system information data to the Product Information tab in the Administration panel. This provides administrators with quick access to essential system details, such as the server deployment type (e.g., Docker, Kubernetes), install path, Java version, and Java parameters;
|
||||
- The global access server URL has been added to the console log, making it easier to locate server installation information directly within the logs;
|
||||
- New environment variables were introduced for theme styling, SQL editor, and log viewer settings. You can use them for quick setup during the initial Docker configuration stage.
|
||||
- Log records now capture create, update, and delete actions for users, teams, and connections for improved tracking and transparency.
|
||||
- LDAP authorization:
|
||||
- Added the ability to match users from LDAP configuration with CloudBeaver users;
|
||||
- Added an option to specify a user login as an attribute parameter for LDAP providers;
|
||||
- CloudBeaver now uses EntityID or objectGUID to create new LDAP users in CloudBeaver to ensure uniqueness. This change enhances user identification and prevents conflicts while maintaining backward compatibility for existing users.
|
||||
- Deployment:
|
||||
- CloudBeaver now uses JDK 21 as its base Java image. If you use standard deployment and upgrade scripts, the new Java version will be applied automatically after the product update;
|
||||
- Changed the permission of the Docker volumes directory to enhance security and prevent any insecure actions by the "root" user. All new deployments will use the "dbeaver" user by default. For existing deployments running as the "root" user, this update will automatically adjust file permissions to ensure they are compatible with the new security model. There will be no manual intervention, and the service will continue to run as expected with the updated permissions.
|
||||
- Connections:
|
||||
- Enabled the possibility of switching a database connection to read-only mode. This mode can be activated in the connection dialog. Administrators can set this mode for any connection, while regular users can set it for their private connections only;
|
||||
- For Oracle and SQL Server connections, advanced database settings can now be used in the URL connection mode.
|
||||
- Added support for secure [LDAP authentication over SSL](https://github.com/dbeaver/cloudbeaver/wiki/LDAP-Authentication);
|
||||
- Brute force protection is now supported for LDAP authentication. All authentication methods on the application level have this security mechanism.
|
||||
- SQL Editor:
|
||||
- A new setting to autosave scripts in the SQL editor appeared in global and users' preferences;
|
||||
- Auto-completion has been improved for aliases and camelCase entities.
|
||||
- Data Editor:
|
||||
- Auto-suggestions for column names in the Data Editor filter field were introduced to avoid typing mistakes;
|
||||
- Introduced the ability to insert data in tables without unique keys: you can import data from CSV files or insert entire rows directly via UI;
|
||||
- The collapse of the grouping panel doesn't lead to the complete panel cleaning anymore.
|
||||
- Data transfer:
|
||||
- Added the ability to use default spreadsheet names (e.g. Sheet0, Sheet1) for exporting to XLSX;
|
||||
- An option to replace line break characters on any custom value was added when exporting to CSV.
|
||||
- Navigator tree:
|
||||
- An option to show metadata object comments was added. You can enable it in the database navigator settings panel;
|
||||
- Introduced the ability to create connections not only on the initial level but in folders and sub-folders directly;
|
||||
- Fixed the display of objects with long names (more than 32 characters) - now, such names will be displayed entirely and not in a cropped format.
|
||||
- Drivers:
|
||||
- The MariaDB driver has been updated to version 3.5.1;
|
||||
- The SQLite driver has been updated to version 3.48.0.0.
|
||||
- Improved table rendering to scale column width depending on the content;
|
||||
- Accessibility: improved keyboard navigation by sorting buttons in column headers.
|
||||
- General:
|
||||
- Added the ability to configure the default database or schema in the connection configuration;
|
||||
- Enhanced initial configuration stage security: a server needs to be restarted if the initial setup time exceeds 1 hour;
|
||||
- Improved Navigation tree performance: lost connection does not lead to the application freezing anymore;
|
||||
- Data transfer: Improved export/import functionality performance by optimizing disk memory consumption;
|
||||
- Vietnamese localization has been added (thanks to [0xhanh](https://github.com/0xhanh)).
|
||||
- Databases and drivers:
|
||||
- Clickhouse: driver has been updated to version 0.8.5;
|
||||
- DuckDB: expanded the list of system objects that can be hidden in the Navigation tree;
|
||||
- LibSQL: added the ability to connect using token authentication;
|
||||
- Oracle: users' DDL in Oracle is displayed in the metadata editor on the corresponding tab for users with Oracle administration permissions;
|
||||
- SQLite: added information about a table's Strict mode to the table metadata section (thanks to [eusebe-cda](https://github.com/eusebe-cda)).
|
||||
|
||||
## Contribution
|
||||
As a community-driven open-source project, we warmly welcome contributions through GitHub pull requests.
|
||||
|
||||
[We are happy to reward](https://dbeaver.com/help-dbeaver/) our most active contributors every major sprint.
|
||||
The most significant contribution to our code for the major release 24.3.0 was made by:
|
||||
1. [cashlifei](https://github.com/cashlifei)
|
||||
The most significant contribution to our code for the major release 25.1.0 was made by:
|
||||
1. [0xhanh](https://github.com/0xhanh) - for Vietnamese localization.
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
# artifacts
|
||||
lib
|
||||
out
|
||||
dist
|
||||
node_modules
|
||||
|
||||
# Yarn
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
!.yarn/sdks/**
|
||||
|
||||
# Swap the comments on the following lines if you wish to use zero-installs
|
||||
# In that case, don't forget to run `yarn config set enableGlobalCache false`!
|
||||
@@ -11,9 +19,3 @@
|
||||
|
||||
#!.yarn/cache
|
||||
.pnp.*
|
||||
|
||||
# artifacts
|
||||
lib
|
||||
out
|
||||
dist
|
||||
node_modules
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "prettier",
|
||||
"version": "3.5.1-sdk",
|
||||
"version": "3.6.2-sdk",
|
||||
"main": "./index.cjs",
|
||||
"type": "commonjs",
|
||||
"bin": "./bin/prettier.cjs"
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require typescript/bin/tsserver
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real typescript/bin/tsserver your application uses
|
||||
module.exports = wrapWithUserWrapper(absRequire(`typescript/bin/tsserver`));
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"name": "typescript",
|
||||
"version": "5.7.3-sdk",
|
||||
"main": "./lib/typescript.js",
|
||||
"type": "commonjs",
|
||||
"bin": {
|
||||
"tsc": "./bin/tsc",
|
||||
"tsserver": "./bin/tsserver"
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
Root;
|
||||
}
|
||||
|
||||
.mlln6zg7-0-0-beta-50 {
|
||||
.mlln6zg7-0-0-beta-55 {
|
||||
@layer rdg.MeasuringCell {
|
||||
contain: strict;
|
||||
grid-row: 1;
|
||||
@@ -24,7 +24,7 @@
|
||||
}
|
||||
|
||||
|
||||
.cj343x07-0-0-beta-50 {
|
||||
.cj343x07-0-0-beta-55 {
|
||||
@layer rdg.Cell {
|
||||
/* max-content does not work with size containment
|
||||
* dynamically switching between different containment styles incurs a heavy relayout penalty
|
||||
@@ -53,7 +53,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.csofj7r7-0-0-beta-50 {
|
||||
.csofj7r7-0-0-beta-55 {
|
||||
@layer rdg.Cell {
|
||||
position: sticky;
|
||||
/* Should have a higher value than 0 to show up above unfrozen cells */
|
||||
@@ -66,8 +66,33 @@
|
||||
}
|
||||
}
|
||||
|
||||
.ch2wcw87-0-0-beta-55 {
|
||||
@layer rdg.DragHandle {
|
||||
--rdg-drag-handle-size: 8px;
|
||||
z-index: 0;
|
||||
cursor: move;
|
||||
inline-size: var(--rdg-drag-handle-size);
|
||||
block-size: var(--rdg-drag-handle-size);
|
||||
background-color: var(--rdg-selection-color);
|
||||
place-self: end;
|
||||
|
||||
.c1bn88vv7-0-0-beta-50 {
|
||||
&:hover {
|
||||
--rdg-drag-handle-size: 16px;
|
||||
border: 2px solid var(--rdg-selection-color);
|
||||
background-color: var(--rdg-background-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c1wvphzh7-0-0-beta-55 {
|
||||
@layer rdg.DragHandle {
|
||||
z-index: 1;
|
||||
position: sticky;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.c1bn88vv7-0-0-beta-55 {
|
||||
@layer rdg.CheckboxInput {
|
||||
display: block;
|
||||
margin: auto;
|
||||
@@ -86,13 +111,13 @@
|
||||
}
|
||||
|
||||
|
||||
.g1s9ylgp7-0-0-beta-50 {
|
||||
.g1s9ylgp7-0-0-beta-55 {
|
||||
@layer rdg.GroupCellContent {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.cz54e4y7-0-0-beta-50 {
|
||||
.cz54e4y7-0-0-beta-55 {
|
||||
@layer rdg.GroupCellCaret {
|
||||
margin-inline-start: 4px;
|
||||
stroke: currentColor;
|
||||
@@ -107,13 +132,13 @@
|
||||
}
|
||||
|
||||
|
||||
.h44jtk67-0-0-beta-50 {
|
||||
.h44jtk67-0-0-beta-55 {
|
||||
@layer rdg.SortableHeaderCell {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.hcgkhxz7-0-0-beta-50 {
|
||||
.hcgkhxz7-0-0-beta-55 {
|
||||
@layer rdg.SortableHeaderCellName {
|
||||
flex-grow: 1;
|
||||
overflow: clip;
|
||||
@@ -122,69 +147,33 @@
|
||||
}
|
||||
|
||||
|
||||
.c6ra8a37-0-0-beta-50 {
|
||||
.c6ra8a37-0-0-beta-55 {
|
||||
@layer rdg.Cell {
|
||||
background-color: #ccccff;
|
||||
}
|
||||
}
|
||||
|
||||
.cq910m07-0-0-beta-50 {
|
||||
@layer rdg.Cell {
|
||||
background-color: #ccccff;
|
||||
|
||||
&.c6ra8a37-0-0-beta-50 {
|
||||
background-color: #9999ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.c1w9bbhr7-0-0-beta-50 {
|
||||
@layer rdg.DragHandle {
|
||||
--rdg-drag-handle-size: 8px;
|
||||
z-index: 0;
|
||||
cursor: move;
|
||||
inline-size: var(--rdg-drag-handle-size);
|
||||
block-size: var(--rdg-drag-handle-size);
|
||||
background-color: var(--rdg-selection-color);
|
||||
place-self: end;
|
||||
|
||||
&:hover {
|
||||
--rdg-drag-handle-size: 16px;
|
||||
border: 2px solid var(--rdg-selection-color);
|
||||
background-color: var(--rdg-background-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c1creorc7-0-0-beta-50 {
|
||||
@layer rdg.DragHandle {
|
||||
z-index: 1;
|
||||
position: sticky;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.cis5rrm7-0-0-beta-50 {
|
||||
.cis5rrm7-0-0-beta-55 {
|
||||
@layer rdg.EditCell {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.c6l2wv17-0-0-beta-50 {
|
||||
.c6l2wv17-0-0-beta-55 {
|
||||
@layer rdg.HeaderCell {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.c1kqdw7y7-0-0-beta-50 {
|
||||
.c1kqdw7y7-0-0-beta-55 {
|
||||
@layer rdg.HeaderCell {
|
||||
touch-action: none;
|
||||
}
|
||||
}
|
||||
|
||||
.r1y6ywlx7-0-0-beta-50 {
|
||||
.r1y6ywlx7-0-0-beta-55 {
|
||||
@layer rdg.HeaderCell {
|
||||
cursor: col-resize;
|
||||
position: absolute;
|
||||
@@ -195,16 +184,29 @@
|
||||
}
|
||||
}
|
||||
|
||||
.c1bezg5o7-0-0-beta-50 {
|
||||
opacity: 0.5;
|
||||
.c1bezg5o7-0-0-beta-55 {
|
||||
@layer rdg.HeaderCell {
|
||||
background-color: var(--rdg-header-draggable-background-color);
|
||||
}
|
||||
}
|
||||
|
||||
.c1vc96037-0-0-beta-50 {
|
||||
background-color: var(--rdg-header-draggable-background-color);
|
||||
.c1vc96037-0-0-beta-55 {
|
||||
@layer rdg.HeaderCell {
|
||||
background-color: var(--rdg-header-draggable-background-color);
|
||||
}
|
||||
}
|
||||
|
||||
.d8rwc9w7-0-0-beta-55 {
|
||||
@layer rdg.HeaderCell {
|
||||
border-radius: 4px;
|
||||
width: fit-content;
|
||||
outline: 2px solid hsl(207, 100%, 50%);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.r1upfr807-0-0-beta-50 {
|
||||
.r1upfr807-0-0-beta-55 {
|
||||
@layer rdg.Row {
|
||||
display: contents;
|
||||
background-color: var(--rdg-background-color);
|
||||
@@ -223,14 +225,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
.r190mhd37-0-0-beta-50 {
|
||||
.r190mhd37-0-0-beta-55 {
|
||||
@layer rdg.FocusSink {
|
||||
outline: 2px solid var(--rdg-selection-color);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
.r139qu9m7-0-0-beta-50 {
|
||||
.r139qu9m7-0-0-beta-55 {
|
||||
@layer rdg.FocusSink {
|
||||
&::before {
|
||||
content: '';
|
||||
@@ -244,26 +246,26 @@
|
||||
}
|
||||
|
||||
|
||||
.h10tskcx7-0-0-beta-50 {
|
||||
.h10tskcx7-0-0-beta-55 {
|
||||
@layer rdg.HeaderRow {
|
||||
display: contents;
|
||||
background-color: var(--rdg-header-background-color);
|
||||
font-weight: bold;
|
||||
|
||||
& > .cj343x07-0-0-beta-50 {
|
||||
& > .cj343x07-0-0-beta-55 {
|
||||
/* Should have a higher value than 1 to show up above regular cells and the focus sink */
|
||||
z-index: 2;
|
||||
position: sticky;
|
||||
}
|
||||
|
||||
& > .csofj7r7-0-0-beta-50 {
|
||||
& > .csofj7r7-0-0-beta-55 {
|
||||
z-index: 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.a3ejtar7-0-0-beta-50 {
|
||||
.a3ejtar7-0-0-beta-55 {
|
||||
@layer rdg.SortIcon {
|
||||
fill: currentColor;
|
||||
|
||||
@@ -274,7 +276,7 @@
|
||||
}
|
||||
|
||||
|
||||
.rnvodz57-0-0-beta-50 {
|
||||
.rnvodz57-0-0-beta-55 {
|
||||
@layer rdg.Defaults {
|
||||
*,
|
||||
*::before,
|
||||
@@ -285,7 +287,7 @@
|
||||
|
||||
@layer rdg.Root {
|
||||
--rdg-color: #000; --rdg-border-color: #ddd; --rdg-summary-border-color: #aaa; --rdg-background-color: hsl(0deg 0% 100%); --rdg-header-background-color: hsl(0deg 0% 97.5%); --rdg-header-draggable-background-color: hsl(0deg 0% 90.5%); --rdg-row-hover-background-color: hsl(0deg 0% 96%); --rdg-row-selected-background-color: hsl(207deg 76% 92%); --rdg-row-selected-hover-background-color: hsl(207deg 76% 88%); --rdg-checkbox-focus-color: hsl(207deg 100% 69%);
|
||||
--rdg-selection-color: #66afe9;
|
||||
--rdg-selection-color: hsl(207, 75%, 66%);
|
||||
--rdg-font-size: 14px;
|
||||
--rdg-cell-frozen-box-shadow: 2px 0 5px -2px rgba(136, 136, 136, 0.3);
|
||||
|
||||
@@ -334,30 +336,30 @@
|
||||
}
|
||||
|
||||
> :nth-last-child(1 of .rdg-top-summary-row) {
|
||||
> .cj343x07-0-0-beta-50 {
|
||||
> .cj343x07-0-0-beta-55 {
|
||||
border-block-end: 2px solid var(--rdg-summary-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
> :nth-child(1 of .rdg-bottom-summary-row) {
|
||||
> .cj343x07-0-0-beta-50 {
|
||||
> .cj343x07-0-0-beta-55 {
|
||||
border-block-start: 2px solid var(--rdg-summary-border-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.vlqv91k7-0-0-beta-50 {
|
||||
.vlqv91k7-0-0-beta-55 {
|
||||
@layer rdg.Root {
|
||||
user-select: none;
|
||||
|
||||
& .r1upfr807-0-0-beta-50 {
|
||||
& .r1upfr807-0-0-beta-55 {
|
||||
cursor: move;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.f1lsfrzw7-0-0-beta-50 {
|
||||
.f1lsfrzw7-0-0-beta-55 {
|
||||
@layer rdg.FocusSink {
|
||||
grid-column: 1/-1;
|
||||
pointer-events: none;
|
||||
@@ -366,7 +368,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.f1cte0lg7-0-0-beta-50 {
|
||||
.f1cte0lg7-0-0-beta-55 {
|
||||
@layer rdg.FocusSink {
|
||||
/* Should have a higher value than 3 to show up above header and summary rows */
|
||||
z-index: 3;
|
||||
@@ -374,7 +376,7 @@
|
||||
}
|
||||
|
||||
|
||||
.s8wc6fl7-0-0-beta-50 {
|
||||
.s8wc6fl7-0-0-beta-55 {
|
||||
@layer rdg.SummaryCell {
|
||||
inset-block-start: var(--rdg-summary-row-top);
|
||||
inset-block-end: var(--rdg-summary-row-bottom);
|
||||
@@ -382,42 +384,42 @@
|
||||
}
|
||||
|
||||
|
||||
.skuhp557-0-0-beta-50 {
|
||||
.skuhp557-0-0-beta-55 {
|
||||
@layer rdg.SummaryRow {
|
||||
> .cj343x07-0-0-beta-50 {
|
||||
> .cj343x07-0-0-beta-55 {
|
||||
position: sticky;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tf8l5ub7-0-0-beta-50 {
|
||||
.tf8l5ub7-0-0-beta-55 {
|
||||
@layer rdg.SummaryRow {
|
||||
> .cj343x07-0-0-beta-50 {
|
||||
> .cj343x07-0-0-beta-55 {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
> .csofj7r7-0-0-beta-50 {
|
||||
> .csofj7r7-0-0-beta-55 {
|
||||
z-index: 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.g1yxluv37-0-0-beta-50 {
|
||||
.g1yxluv37-0-0-beta-55 {
|
||||
@layer rdg.GroupedRow {
|
||||
&:not([aria-selected='true']) {
|
||||
background-color: var(--rdg-header-background-color);
|
||||
}
|
||||
|
||||
> .cj343x07-0-0-beta-50:not(:last-child, .csofj7r7-0-0-beta-50),
|
||||
> :nth-last-child(n + 2 of .csofj7r7-0-0-beta-50) {
|
||||
> .cj343x07-0-0-beta-55:not(:last-child, .csofj7r7-0-0-beta-55),
|
||||
> :nth-last-child(n + 2 of .csofj7r7-0-0-beta-55) {
|
||||
border-inline-end: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.t7vyx3i7-0-0-beta-50 {
|
||||
.t7vyx3i7-0-0-beta-55 {
|
||||
@layer rdg.TextEditor {
|
||||
appearance: none;
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"name": "react-data-grid",
|
||||
"version": "7.0.0-beta.50",
|
||||
"version": "7.0.0-beta.55",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./lib/styles.css": "./lib/styles.css",
|
||||
".": {
|
||||
"types": "./lib/index.d.ts",
|
||||
"default": "./lib/bundle.js"
|
||||
"default": "./lib/index.js"
|
||||
}
|
||||
},
|
||||
"browser": "./lib/bundle.js",
|
||||
"main": "./lib/bundle.js",
|
||||
"module": "./lib/bundle.js",
|
||||
"browser": "./lib/index.js",
|
||||
"main": "./lib/index.js",
|
||||
"module": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"files": [
|
||||
"lib"
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"!lib/tests",
|
||||
"!.tsbuildinfo"
|
||||
],
|
||||
"packageManager": "yarn@4.6.0",
|
||||
"packageManager": "yarn@4.9.2",
|
||||
"devDependencies": {
|
||||
"@dbeaver/tsconfig": "workspace:^",
|
||||
"@types/react": "^19",
|
||||
@@ -33,6 +33,7 @@
|
||||
"typescript": "^5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dbeaver/react-dnd": "workspace:^",
|
||||
"@dbeaver/ui-kit": "workspace:^",
|
||||
"react": "^19",
|
||||
"react-data-grid": "file:./artifacts",
|
||||
|
||||
@@ -4,19 +4,29 @@ import { DataGridCellContext, type IDataGridCellRenderer } from './DataGridCellC
|
||||
import { createCellMouseEvent } from './eventUtils.js';
|
||||
import { DataGridCellInnerContext, type IDataGridCellInnerContext } from './DataGridCellInnerContext.js';
|
||||
import { useGridReactiveValue } from './useGridReactiveValue.js';
|
||||
import { HeaderDnDContext } from './useHeaderDnD.js';
|
||||
|
||||
export const BaseCell = memo(function BaseCell<TRow, TSummaryRow>(props: CellRendererProps<TRow, TSummaryRow>) {
|
||||
const cellContext = use(DataGridCellContext);
|
||||
const tooltip = useGridReactiveValue(cellContext?.cellTooltip, props.rowIdx, props.column.idx);
|
||||
const dndContext = use(HeaderDnDContext)!;
|
||||
const virtualColIdx = props.column.idx;
|
||||
const dataColIdx = dndContext.getDataColIdx(props.column.idx);
|
||||
const rowIdx = props.rowIdx;
|
||||
const tooltip = useGridReactiveValue(cellContext?.cellTooltip, rowIdx, dataColIdx);
|
||||
|
||||
function handleClick(event: React.MouseEvent<HTMLDivElement>) {
|
||||
props.onClick?.(
|
||||
props.onCellClick?.(
|
||||
{
|
||||
rowIdx: props.rowIdx,
|
||||
rowIdx,
|
||||
row: props.row,
|
||||
column: props.column,
|
||||
selectCell(enableEditor) {
|
||||
props.selectCell({ rowIdx: props.rowIdx, idx: props.column.idx }, enableEditor);
|
||||
props.selectCell(
|
||||
{ rowIdx, idx: virtualColIdx },
|
||||
{
|
||||
enableEditor,
|
||||
},
|
||||
);
|
||||
},
|
||||
},
|
||||
createCellMouseEvent(event),
|
||||
@@ -24,13 +34,13 @@ export const BaseCell = memo(function BaseCell<TRow, TSummaryRow>(props: CellRen
|
||||
}
|
||||
|
||||
function handleDoubleClick(event: React.MouseEvent<HTMLDivElement>) {
|
||||
props.onDoubleClick?.(
|
||||
props.onCellDoubleClick?.(
|
||||
{
|
||||
rowIdx: props.rowIdx,
|
||||
rowIdx,
|
||||
row: props.row,
|
||||
column: props.column,
|
||||
selectCell(enableEditor) {
|
||||
props.selectCell({ rowIdx: props.rowIdx, idx: props.column.idx }, enableEditor);
|
||||
props.selectCell({ rowIdx, idx: virtualColIdx }, { enableEditor });
|
||||
},
|
||||
},
|
||||
createCellMouseEvent(event),
|
||||
@@ -38,13 +48,13 @@ export const BaseCell = memo(function BaseCell<TRow, TSummaryRow>(props: CellRen
|
||||
}
|
||||
|
||||
function handleContextMenu(event: React.MouseEvent<HTMLDivElement>) {
|
||||
props.onContextMenu?.(
|
||||
props.onCellContextMenu?.(
|
||||
{
|
||||
rowIdx: props.rowIdx,
|
||||
rowIdx,
|
||||
row: props.row,
|
||||
column: props.column,
|
||||
selectCell(enableEditor) {
|
||||
props.selectCell({ rowIdx: props.rowIdx, idx: props.column.idx }, enableEditor);
|
||||
props.selectCell({ rowIdx, idx: virtualColIdx }, { enableEditor });
|
||||
},
|
||||
},
|
||||
createCellMouseEvent(event),
|
||||
@@ -52,7 +62,16 @@ export const BaseCell = memo(function BaseCell<TRow, TSummaryRow>(props: CellRen
|
||||
}
|
||||
|
||||
const mappedProps = useMemo(
|
||||
() => ({ ...props, isFocused: props.isCellSelected, onClick: handleClick, onDoubleClick: handleDoubleClick, onContextMenu: handleContextMenu }),
|
||||
() => ({
|
||||
...props,
|
||||
onCellClick: undefined,
|
||||
onCellContextMenu: undefined,
|
||||
onCellDoubleClick: undefined,
|
||||
isFocused: props.isCellSelected,
|
||||
onClick: handleClick,
|
||||
onDoubleClick: handleDoubleClick,
|
||||
onContextMenu: handleContextMenu,
|
||||
}),
|
||||
Object.values(props),
|
||||
);
|
||||
|
||||
@@ -63,9 +82,9 @@ export const BaseCell = memo(function BaseCell<TRow, TSummaryRow>(props: CellRen
|
||||
<Cell
|
||||
{...props}
|
||||
title={tooltip}
|
||||
onClick={(_, event) => onClick?.(event)}
|
||||
onDoubleClick={(_, event) => onDoubleClick?.(event)}
|
||||
onContextMenu={(_, event) => onContextMenu?.(event)}
|
||||
onCellClick={(_, event) => onClick?.(event)}
|
||||
onCellDoubleClick={(_, event) => onDoubleClick?.(event)}
|
||||
onCellContextMenu={(_, event) => onContextMenu?.(event)}
|
||||
{...rest}
|
||||
isCellSelected={props.isCellSelected || rest.isFocused || false}
|
||||
/>
|
||||
@@ -74,7 +93,7 @@ export const BaseCell = memo(function BaseCell<TRow, TSummaryRow>(props: CellRen
|
||||
[...Object.values(props), tooltip],
|
||||
);
|
||||
|
||||
const cellElement = useGridReactiveValue(cellContext?.cellElement, props.rowIdx, props.column.idx, mappedProps, renderDefaultCell);
|
||||
const cellElement = useGridReactiveValue(cellContext?.cellElement, rowIdx, dataColIdx, mappedProps, renderDefaultCell);
|
||||
|
||||
const innerCellContext = useMemo<IDataGridCellInnerContext>(() => ({ isFocused: props.isCellSelected }), [props.isCellSelected]);
|
||||
return <DataGridCellInnerContext value={innerCellContext}>{cellElement ?? <Cell title={tooltip} {...props} />}</DataGridCellInnerContext>;
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
}
|
||||
|
||||
@layer components.rdg.Cell {
|
||||
.rdg {
|
||||
--dbv-kit-icon-btn-outline-width: 1px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.rdg-cell-frozen {
|
||||
&:nth-last-child(1 of &) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { forwardRef, useImperativeHandle, useMemo, useRef } from 'react';
|
||||
import { DataGrid as DataGridBase, type ColumnOrColumnGroup, type CellSelectArgs, type DataGridHandle } from 'react-data-grid';
|
||||
import { forwardRef, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
||||
import { DataGrid as DataGridBase, type ColumnOrColumnGroup, type CellSelectArgs, type DataGridHandle, type ColumnWidth, type ColumnWidths } from 'react-data-grid';
|
||||
import { rowRenderer } from './renderers/rowRenderer.js';
|
||||
import { cellRenderer } from './renderers/cellRenderer.js';
|
||||
import { DataGridCellHeaderContext, type IDataGridHeaderCellContext } from './DataGridHeaderCellContext.js';
|
||||
@@ -12,6 +12,7 @@ import { mapRenderHeaderCell } from './mapRenderHeaderCell.js';
|
||||
import { mapEditCellRenderer } from './mapEditCellRenderer.js';
|
||||
import { DataGridRowContext, type IDataGridRowContext } from './DataGridRowContext.js';
|
||||
import './DataGrid.css';
|
||||
import { HeaderDnDContext, useHeaderDnD } from './useHeaderDnD.js';
|
||||
|
||||
export interface ICellPosition {
|
||||
rowIdx: number;
|
||||
@@ -46,9 +47,13 @@ export const DataGrid = forwardRef<DataGridRef, DataGridProps>(function DataGrid
|
||||
headerElement,
|
||||
getHeaderWidth,
|
||||
headerText,
|
||||
getHeaderOrder,
|
||||
getHeaderResizable,
|
||||
columnSortable,
|
||||
getHeaderHeight,
|
||||
getHeaderPinned,
|
||||
columnSortingState,
|
||||
getHeaderDnD,
|
||||
cell,
|
||||
cellText,
|
||||
cellElement,
|
||||
@@ -59,20 +64,23 @@ export const DataGrid = forwardRef<DataGridRef, DataGridProps>(function DataGrid
|
||||
rowCount,
|
||||
getRowId,
|
||||
getRowHeight,
|
||||
onHeaderReorder,
|
||||
onScroll,
|
||||
onScrollToBottom,
|
||||
onFocus,
|
||||
onCellChange,
|
||||
onColumnSort,
|
||||
onHeaderKeyDown,
|
||||
children,
|
||||
className,
|
||||
onCellKeyDown,
|
||||
},
|
||||
ref,
|
||||
) {
|
||||
const [columnWidths, setColumnWidths] = useState<ColumnWidths>(() => new Map<string, ColumnWidth>());
|
||||
const rowsCount = useGridReactiveValue(rowCount);
|
||||
const columnsCount = useGridReactiveValue(columnCount);
|
||||
|
||||
const gridKey = useRef(0);
|
||||
const rowsCountRef = useRef(rowsCount);
|
||||
const innerGridRef = useRef<DataGridHandle>(null);
|
||||
const columns = new Array<ColumnOrColumnGroup<IInnerRow, unknown>>(columnsCount)
|
||||
@@ -87,21 +95,25 @@ export const DataGrid = forwardRef<DataGridRef, DataGridProps>(function DataGrid
|
||||
minWidth: 26,
|
||||
editable: row => getCellEditable?.(row.idx, i) ?? false,
|
||||
frozen: getHeaderPinned?.(i),
|
||||
renderHeaderCell: mapRenderHeaderCell,
|
||||
renderCell: mapCellContentRenderer,
|
||||
renderEditCell: mapEditCellRenderer,
|
||||
renderHeaderCell: mapRenderHeaderCell(i),
|
||||
renderCell: mapCellContentRenderer(i),
|
||||
renderEditCell: mapEditCellRenderer(i),
|
||||
};
|
||||
});
|
||||
|
||||
const dndHeaderContext = useHeaderDnD({ columns, onReorder: onHeaderReorder, getCanDrag: getHeaderDnD, getHeaderOrder });
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
selectCell: (position: ICellPosition) => {
|
||||
innerGridRef.current?.selectCell({ idx: position.colIdx, rowIdx: position.rowIdx });
|
||||
innerGridRef.current?.selectCell({ idx: dndHeaderContext.getDataColIdx(position.colIdx), rowIdx: position.rowIdx });
|
||||
},
|
||||
scrollToCell: (position: Partial<ICellPosition>) => {
|
||||
innerGridRef.current?.scrollToCell({ idx: position.colIdx, rowIdx: position.rowIdx });
|
||||
innerGridRef.current?.scrollToCell({ idx: position.colIdx && dndHeaderContext.getDataColIdx(position.colIdx), rowIdx: position.rowIdx });
|
||||
},
|
||||
openEditor: (position: ICellPosition) => {
|
||||
innerGridRef.current?.selectCell({ idx: position.colIdx, rowIdx: position.rowIdx }, true);
|
||||
innerGridRef.current?.selectCell({ idx: dndHeaderContext.getDataColIdx(position.colIdx), rowIdx: position.rowIdx }, {
|
||||
enableEditor: true,
|
||||
});
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -110,12 +122,11 @@ export const DataGrid = forwardRef<DataGridRef, DataGridProps>(function DataGrid
|
||||
rowsCountRef.current = rowsCount;
|
||||
|
||||
if (previousRowCount === 0) {
|
||||
// we trigger columns size recalculation when rows are added
|
||||
gridKey.current++;
|
||||
setColumnWidths(new Map<string, ColumnWidth>());
|
||||
}
|
||||
}
|
||||
|
||||
const rows = useMemo(
|
||||
let rows = useMemo(
|
||||
() =>
|
||||
new Array<IInnerRow>(rowsCount).fill({ idx: 0 }).map((_, i) => ({
|
||||
idx: i,
|
||||
@@ -124,34 +135,47 @@ export const DataGrid = forwardRef<DataGridRef, DataGridProps>(function DataGrid
|
||||
);
|
||||
|
||||
function handleCellFocus(args: CellSelectArgs<IInnerRow, unknown>) {
|
||||
onFocus?.({ colIdx: args.column.idx, rowIdx: args.rowIdx });
|
||||
onFocus?.({ colIdx: dndHeaderContext.getDataColIdx(args.column.idx), rowIdx: args.rowIdx });
|
||||
}
|
||||
|
||||
function handleCellKeyDown(args: CellSelectArgs<IInnerRow, unknown>, event: DataGridCellKeyboardEvent) {
|
||||
onCellKeyDown?.({ colIdx: dndHeaderContext.getDataColIdx(args.column.idx), rowIdx: args.rowIdx }, event);
|
||||
}
|
||||
|
||||
const isMeasurementRender = columnWidths.size === 0 && columnCount.get() > 0;
|
||||
|
||||
if (isMeasurementRender) {
|
||||
rows = rows.slice(0, 100);
|
||||
}
|
||||
|
||||
return (
|
||||
<DataGridRowContext value={{ rowCount, onScrollToBottom }}>
|
||||
<DataGridCellContext value={{ cell, cellText, cellElement, cellTooltip, onCellChange }}>
|
||||
<DataGridCellHeaderContext value={{ headerElement, headerText }}>
|
||||
<DataGridBase
|
||||
key={gridKey.current}
|
||||
ref={innerGridRef}
|
||||
columns={columns}
|
||||
rows={rows}
|
||||
className={className}
|
||||
headerRowHeight={getHeaderHeight?.()}
|
||||
onScroll={onScroll}
|
||||
rowHeight={getRowHeight ? row => getRowHeight(row.idx) : undefined}
|
||||
rowKeyGetter={getRowId ? row => getRowId(row.idx) : undefined}
|
||||
onSelectedCellChange={handleCellFocus}
|
||||
onCellKeyDown={onCellKeyDown ? (args, event) => onCellKeyDown({ rowIdx: args.rowIdx, colIdx: args.column.idx }, event) : undefined}
|
||||
renderers={{
|
||||
renderRow: rowRenderer,
|
||||
renderCell: cellRenderer,
|
||||
noRowsFallback: children,
|
||||
}}
|
||||
minimumRowsToRender={100}
|
||||
/>
|
||||
</DataGridCellHeaderContext>
|
||||
</DataGridCellContext>
|
||||
</DataGridRowContext>
|
||||
<HeaderDnDContext value={dndHeaderContext}>
|
||||
<DataGridRowContext value={{ rowCount, onScrollToBottom }}>
|
||||
<DataGridCellContext value={{ cell, cellText, cellElement, cellTooltip, onCellChange }}>
|
||||
<DataGridCellHeaderContext value={{ headerElement, headerText, getHeaderDnD, columnSortable, onColumnSort, columnSortingState, onHeaderKeyDown }}>
|
||||
<DataGridBase
|
||||
ref={innerGridRef}
|
||||
columns={dndHeaderContext.columns}
|
||||
enableVirtualization={!isMeasurementRender}
|
||||
rows={rows}
|
||||
className={className}
|
||||
headerRowHeight={getHeaderHeight?.()}
|
||||
rowHeight={getRowHeight ? row => getRowHeight(row.idx) : undefined}
|
||||
rowKeyGetter={getRowId ? row => getRowId(row.idx) : undefined}
|
||||
columnWidths={columnWidths}
|
||||
renderers={{
|
||||
renderRow: rowRenderer,
|
||||
renderCell: cellRenderer,
|
||||
noRowsFallback: children,
|
||||
}}
|
||||
onScroll={onScroll}
|
||||
onSelectedCellChange={handleCellFocus}
|
||||
onCellKeyDown={handleCellKeyDown}
|
||||
onColumnWidthsChange={setColumnWidths}
|
||||
/>
|
||||
</DataGridCellHeaderContext>
|
||||
</DataGridCellContext>
|
||||
</DataGridRowContext>
|
||||
</HeaderDnDContext>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -4,10 +4,17 @@ import type { IGridReactiveValue } from './IGridReactiveValue.js';
|
||||
export interface IDataGridHeaderCellContext {
|
||||
headerElement?: IGridReactiveValue<React.ReactNode, [colIdx: number]>;
|
||||
headerText?: IGridReactiveValue<string, [colIdx: number]>;
|
||||
getHeaderOrder?: () => number[];
|
||||
getHeaderWidth?: (colIdx: number) => number | string | null;
|
||||
getHeaderResizable?: (colIdx: number) => boolean;
|
||||
getHeaderHeight?: () => number;
|
||||
getHeaderPinned?: (colIdx: number) => boolean;
|
||||
getHeaderDnD?: (colIdx: number) => boolean;
|
||||
onHeaderReorder?: (from: number, to: number) => void;
|
||||
columnSortingState?: IGridReactiveValue<'asc' | 'desc' | undefined | null, [colIdx: number]>;
|
||||
columnSortable?: IGridReactiveValue<boolean, [colIdx: number]>;
|
||||
onColumnSort?: (colIdx: number, order: 'asc' | 'desc' | null, isMultiple: boolean) => void;
|
||||
onHeaderKeyDown?: (event: React.KeyboardEvent) => void;
|
||||
}
|
||||
|
||||
export const DataGridCellHeaderContext = createContext<IDataGridHeaderCellContext | null>(null);
|
||||
|
||||
@@ -4,11 +4,12 @@ import { Checkbox, clsx, Focusable } from '@dbeaver/ui-kit';
|
||||
interface Props {
|
||||
value: boolean | null;
|
||||
className?: string;
|
||||
focusable?: boolean;
|
||||
onClick?: React.MouseEventHandler<HTMLElement>;
|
||||
onKeyDown?: React.KeyboardEventHandler<HTMLElement>;
|
||||
}
|
||||
|
||||
export function BooleanFormatter({ value, className, onClick, onKeyDown }: Props) {
|
||||
export function BooleanFormatter({ value, className, onClick, onKeyDown, focusable }: Props) {
|
||||
const handleKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {
|
||||
if (event.code === 'Enter' || event.code === 'Space') {
|
||||
event.preventDefault();
|
||||
@@ -17,11 +18,12 @@ export function BooleanFormatter({ value, className, onClick, onKeyDown }: Props
|
||||
};
|
||||
return (
|
||||
<Focusable
|
||||
focusable={focusable}
|
||||
className={clsx('tw:flex tw:items-center tw:outline-none tw:hover:cursor-pointer', className)}
|
||||
onKeyDown={handleKeyDown}
|
||||
onClick={onClick}
|
||||
>
|
||||
{value === null ? <NullFormatter /> : <Checkbox className="tw:data-disabled:opacity-100" disabled size="small" checked={value} />}
|
||||
{value === null ? <NullFormatter /> : <Checkbox className="tw:data-disabled:opacity-100!" disabled size="small" checked={value} />}
|
||||
</Focusable>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ export * from './DataGridCellInnerContext.js';
|
||||
export * from './IGridReactiveValue.js';
|
||||
export * from './useCreateGridReactiveValue.js';
|
||||
export * from './useGridReactiveValue.js';
|
||||
export * from './reorderArray.js';
|
||||
|
||||
export * from './formatters/NullFormatter.js';
|
||||
export * from './formatters/BooleanFormatter.js';
|
||||
|
||||
@@ -2,6 +2,8 @@ import type { RenderCellProps } from 'react-data-grid';
|
||||
import type { IInnerRow } from './IInnerRow.js';
|
||||
import { CellContentRenderer } from './renderers/CellContentRenderer.js';
|
||||
|
||||
export function mapCellContentRenderer({ rowIdx, column }: RenderCellProps<IInnerRow, unknown>) {
|
||||
return <CellContentRenderer rowIdx={rowIdx} colIdx={column.idx} />;
|
||||
export function mapCellContentRenderer(colIdx: number) {
|
||||
return function RenderCell({ rowIdx }: RenderCellProps<IInnerRow, unknown>) {
|
||||
return <CellContentRenderer rowIdx={rowIdx} colIdx={colIdx} />;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import type { RenderEditCellProps } from 'react-data-grid';
|
||||
import type { IInnerRow } from './IInnerRow.js';
|
||||
import { TextEditor } from './editors/TextEditor.js';
|
||||
|
||||
export function mapEditCellRenderer({ rowIdx, column, onClose }: RenderEditCellProps<IInnerRow, unknown>) {
|
||||
return <TextEditor rowIdx={rowIdx} colIdx={column.idx} onClose={() => onClose()} />;
|
||||
export function mapEditCellRenderer(colIdx: number) {
|
||||
return function RenderEditCell({ rowIdx, onClose }: RenderEditCellProps<IInnerRow, unknown>) {
|
||||
return <TextEditor rowIdx={rowIdx} colIdx={colIdx} onClose={() => onClose()} />;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import type { RenderHeaderCellProps } from 'react-data-grid';
|
||||
import type { IInnerRow } from './IInnerRow.js';
|
||||
import { HeaderCellContentRenderer } from './renderers/HeaderCellContentRenderer.js';
|
||||
|
||||
export function mapRenderHeaderCell({ column }: RenderHeaderCellProps<IInnerRow, unknown>) {
|
||||
return <HeaderCellContentRenderer colIdx={column.idx} />;
|
||||
export function mapRenderHeaderCell(colIdx: number) {
|
||||
return function RenderHeaderCell({ tabIndex }: RenderHeaderCellProps<IInnerRow, unknown>) {
|
||||
return <HeaderCellContentRenderer colIdx={colIdx} tabIndex={tabIndex} />;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,13 +1,85 @@
|
||||
import { use } from 'react';
|
||||
import { memo, use } from 'react';
|
||||
import { useDrag, useDrop, type DnDStoreProvider } from '@dbeaver/react-dnd';
|
||||
import { DataGridCellHeaderContext } from '../DataGridHeaderCellContext.js';
|
||||
import { useGridReactiveValue } from '../useGridReactiveValue.js';
|
||||
import { HeaderDnDContext } from '../useHeaderDnD.js';
|
||||
import { OrderButton } from './OrderButton.js';
|
||||
|
||||
interface Props {
|
||||
colIdx: number;
|
||||
tabIndex?: number;
|
||||
}
|
||||
export function HeaderCellContentRenderer({ colIdx }: Props) {
|
||||
|
||||
export const HeaderCellContentRenderer = memo(function HeaderCellContentRenderer({ colIdx, tabIndex }: Props) {
|
||||
const dndHeaderContext = use(HeaderDnDContext);
|
||||
const cellHeaderContext = use(DataGridCellHeaderContext);
|
||||
const headerElement = useGridReactiveValue(cellHeaderContext?.headerElement, colIdx);
|
||||
const getHeaderText = useGridReactiveValue(headerElement ? undefined : cellHeaderContext?.headerText, colIdx);
|
||||
return headerElement ?? getHeaderText ?? '';
|
||||
}
|
||||
const isColumnSortable = useGridReactiveValue(cellHeaderContext?.columnSortable, colIdx);
|
||||
const onColumnSort = cellHeaderContext?.onColumnSort;
|
||||
const onHeaderKeyDown = cellHeaderContext?.onHeaderKeyDown;
|
||||
const sortingState = useGridReactiveValue(cellHeaderContext?.columnSortingState, colIdx);
|
||||
|
||||
const draggable = dndHeaderContext?.getCanDrag?.(colIdx) ?? false;
|
||||
const drag = useDrag({
|
||||
draggable,
|
||||
onDragStart(event, store) {
|
||||
if (dndHeaderContext?.id) {
|
||||
store.setData('dbeaver-react-data-grid-id', dndHeaderContext?.id);
|
||||
}
|
||||
store.setData('dbeaver-react-data-grid-col-idx', colIdx);
|
||||
},
|
||||
onDragEnd() {
|
||||
dndHeaderContext?.onDragEnd(colIdx);
|
||||
},
|
||||
});
|
||||
|
||||
function canDrop(event: React.DragEvent<HTMLElement>, store: DnDStoreProvider | null) {
|
||||
const gridId = store?.getData('dbeaver-react-data-grid-id');
|
||||
return gridId === dndHeaderContext?.id;
|
||||
}
|
||||
const drop = useDrop({
|
||||
canDrop,
|
||||
onDragOver(event, store) {
|
||||
if (!canDrop(event, store)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dragColIdx = store?.getData('dbeaver-react-data-grid-col-idx');
|
||||
const position = event.clientX - event.currentTarget.getBoundingClientRect().left;
|
||||
const width = event.currentTarget.offsetWidth;
|
||||
const isAfter = position > width / 2;
|
||||
|
||||
dndHeaderContext?.onDragOver(dragColIdx, colIdx, isAfter);
|
||||
},
|
||||
});
|
||||
|
||||
function handleSort(e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>) {
|
||||
if (!onColumnSort) return;
|
||||
|
||||
const nextSortState = sortingState === 'asc' ? 'desc' : sortingState === 'desc' ? null : 'asc';
|
||||
onColumnSort(colIdx, nextSortState, e.ctrlKey || e.metaKey);
|
||||
}
|
||||
|
||||
function onKeyDown(event: React.KeyboardEvent<HTMLElement>) {
|
||||
onHeaderKeyDown?.(event);
|
||||
|
||||
if ((event.key === 'Enter' || event.key === ' ') && isColumnSortable && onColumnSort) {
|
||||
event.preventDefault();
|
||||
handleSort(event);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
onKeyDown={onKeyDown}
|
||||
tabIndex={tabIndex}
|
||||
className="tw:w-full tw:h-full tw:content-center tw:flex tw:items-center tw:justify-between tw:gap-1 tw:outline-none tw:group"
|
||||
{...drag.props}
|
||||
{...drop.props}
|
||||
>
|
||||
<span className="tw:overflow-hidden tw:h-full tw:text-ellipsis">{headerElement ?? getHeaderText ?? ''}</span>
|
||||
{isColumnSortable && onColumnSort && <OrderButton sortState={sortingState} onClick={handleSort} />}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import { clsx, IconButton, Icon } from '@dbeaver/ui-kit';
|
||||
|
||||
interface OrderButtonProps {
|
||||
sortState?: 'asc' | 'desc' | null;
|
||||
onClick: (e: React.MouseEvent<HTMLElement>) => void;
|
||||
tabIndex?: number;
|
||||
}
|
||||
|
||||
export function OrderButton({ sortState, onClick, tabIndex }: OrderButtonProps) {
|
||||
const svgSortAsc = 'sort-asc';
|
||||
const svgSortDesc = 'sort-desc';
|
||||
const svgSortUnknown = 'sort-unknown';
|
||||
|
||||
const iconSrc = sortState === 'asc' ? svgSortAsc : sortState === 'desc' ? svgSortDesc : svgSortUnknown;
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
variant="secondary"
|
||||
size="small"
|
||||
onClick={onClick}
|
||||
tabIndex={tabIndex}
|
||||
title="Sort by column"
|
||||
aria-label="Sort by column"
|
||||
className={clsx(
|
||||
'tw:opacity-0 tw:group-focus:opacity-100 tw:focus:opacity-100 tw:group-hover:opacity-100 tw:hover:opacity-100 tw:outline-offset-0',
|
||||
sortState && 'tw:opacity-100',
|
||||
)}
|
||||
>
|
||||
<Icon name={iconSrc} />
|
||||
</IconButton>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
export function reorderArray<T>(array: T[], from: number, to: number): T[] {
|
||||
const newArray = [...array];
|
||||
if (from < to) {
|
||||
newArray.splice(to, 0, array[from]!);
|
||||
newArray.splice(from, 1);
|
||||
} else {
|
||||
newArray.splice(from, 1);
|
||||
newArray.splice(to, 0, array[from]!);
|
||||
}
|
||||
return newArray;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
import type { ColumnOrColumnGroup } from 'react-data-grid';
|
||||
import type { IInnerRow } from './IInnerRow.js';
|
||||
import { createContext, useId, useMemo, useState } from 'react';
|
||||
import { reorderArray } from './reorderArray.js';
|
||||
|
||||
interface IHeaderDnDOptions {
|
||||
columns: Array<ColumnOrColumnGroup<IInnerRow, unknown>>;
|
||||
getCanDrag?: (colIdx: number) => boolean;
|
||||
onReorder?: (from: number, to: number) => void;
|
||||
getHeaderOrder?: () => number[];
|
||||
}
|
||||
|
||||
interface IHeaderDnD {
|
||||
id: string;
|
||||
columns: Array<ColumnOrColumnGroup<IInnerRow, unknown>>;
|
||||
getDataColIdx: (virtualColIdx: number) => number;
|
||||
getVirtualColIdx: (dataColIdx: number) => number;
|
||||
getCanDrag?: (colIdx: number) => boolean;
|
||||
onDragOver: (dragColIdx: number, dropColIdx: number, isAfter: boolean) => void;
|
||||
onDragEnd: (colIdx: number) => void;
|
||||
}
|
||||
|
||||
export const HeaderDnDContext = createContext<IHeaderDnD | null>(null);
|
||||
|
||||
export function useHeaderDnD({ columns, getCanDrag, onReorder, getHeaderOrder }: IHeaderDnDOptions): IHeaderDnD {
|
||||
const id = useId();
|
||||
const [activeDnDElement, setActiveDnDElement] = useState<number | null>(null);
|
||||
const [dragOverElement, setDragOverElement] = useState<[number, boolean] | null>(null);
|
||||
|
||||
function getDataColIdx(virtualColIdx: number) {
|
||||
// Given a visible (ordered) column index, return the original data column index
|
||||
const order = getHeaderOrder?.();
|
||||
if (order) {
|
||||
return order[virtualColIdx] ?? virtualColIdx;
|
||||
}
|
||||
return virtualColIdx;
|
||||
}
|
||||
|
||||
function getVirtualColIdx(dataColIdx: number) {
|
||||
// Given the original data column index, return its visible (ordered) index
|
||||
const order = getHeaderOrder?.();
|
||||
if (order) {
|
||||
return order.indexOf(dataColIdx);
|
||||
}
|
||||
return dataColIdx;
|
||||
}
|
||||
|
||||
function onDragEnd(dragColIdx: number) {
|
||||
setActiveDnDElement(null);
|
||||
setDragOverElement(null);
|
||||
|
||||
if (dragOverElement) {
|
||||
const isAfter = dragOverElement?.[1];
|
||||
let to = dragOverElement?.[0];
|
||||
|
||||
if (isAfter) {
|
||||
to = getDataColIdx(getVirtualColIdx(to) + 1);
|
||||
}
|
||||
|
||||
onReorder?.(dragColIdx, to);
|
||||
}
|
||||
}
|
||||
|
||||
function onDragOver(dragColIdx: number, dropColIdx: number, isAfter: boolean) {
|
||||
setActiveDnDElement(dragColIdx);
|
||||
if (dragColIdx !== dropColIdx) {
|
||||
setDragOverElement([dropColIdx, isAfter]);
|
||||
}
|
||||
}
|
||||
|
||||
columns = useMemo(() => columns.map((col, idx) => columns[getDataColIdx(idx)]!), [columns, getHeaderOrder]);
|
||||
|
||||
if (activeDnDElement !== null && dragOverElement !== null) {
|
||||
const from = getVirtualColIdx(activeDnDElement);
|
||||
let to = getVirtualColIdx(dragOverElement[0]);
|
||||
const isAfter = dragOverElement[1];
|
||||
|
||||
if (isAfter) {
|
||||
to++;
|
||||
}
|
||||
|
||||
columns = reorderArray(columns, from, to);
|
||||
}
|
||||
|
||||
return {
|
||||
id,
|
||||
columns,
|
||||
getDataColIdx,
|
||||
getVirtualColIdx,
|
||||
getCanDrag,
|
||||
onDragOver,
|
||||
onDragEnd,
|
||||
};
|
||||
}
|
||||
@@ -14,6 +14,9 @@
|
||||
"src"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../react-dnd"
|
||||
},
|
||||
{
|
||||
"path": "../ui-kit"
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
# @dbeaver/react-dnd
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "@dbeaver/react-dnd",
|
||||
"type": "module",
|
||||
"sideEffects": [],
|
||||
"exports": {
|
||||
".": "./lib/index.js",
|
||||
"./*": "./lib/*.js"
|
||||
},
|
||||
"scripts": {
|
||||
"clear": "rimraf lib"
|
||||
},
|
||||
"files": [
|
||||
"package.json",
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"CHANGELOG.md",
|
||||
"lib",
|
||||
"!lib/**/*.d.ts.map",
|
||||
"!lib/**/*.test.js",
|
||||
"!lib/**/*.test.d.ts",
|
||||
"!lib/**/*.test.d.ts.map",
|
||||
"!lib/**/*.test.js.map",
|
||||
"!lib/tests",
|
||||
"!.tsbuildinfo"
|
||||
],
|
||||
"packageManager": "yarn@4.9.2",
|
||||
"devDependencies": {
|
||||
"@dbeaver/tsconfig": "workspace:^",
|
||||
"@types/react": "^19",
|
||||
"rimraf": "^6",
|
||||
"typescript": "^5"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^19"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from './useDrag.js';
|
||||
export * from './useDrop.js';
|
||||
export { type DnDStoreProvider } from './store.js';
|
||||
@@ -0,0 +1,46 @@
|
||||
export const DND_STORE_PREFIX = 'application/dbeaver-react-dnd-';
|
||||
|
||||
export interface DnDStoreProvider {
|
||||
getData: (key: string) => any;
|
||||
setData: (key: string, value: any) => void;
|
||||
removeData: () => void;
|
||||
}
|
||||
|
||||
class DnDStore {
|
||||
private data: Map<string, Record<string, any>> = new Map();
|
||||
setData(id: string, key: string, value: any) {
|
||||
if (!this.data.has(id)) {
|
||||
this.data.set(id, {});
|
||||
}
|
||||
this.data.get(id)![key] = value;
|
||||
}
|
||||
getData(id: string, key: string) {
|
||||
return this.data.get(id)?.[key];
|
||||
}
|
||||
removeData(id: string) {
|
||||
this.data.delete(id);
|
||||
}
|
||||
|
||||
getProvider(id: string) {
|
||||
return {
|
||||
getData: (key: string) => this.getData(id, key),
|
||||
setData: (key: string, value: any) => {
|
||||
this.setData(id, key, value);
|
||||
},
|
||||
removeData: () => {
|
||||
this.removeData(id);
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function getStoreProvider(event: React.DragEvent<HTMLElement>): DnDStoreProvider | null {
|
||||
const id = event.dataTransfer.types.find(type => type.startsWith(DND_STORE_PREFIX))?.slice(DND_STORE_PREFIX.length);
|
||||
|
||||
return id ? globalDnDStore.getProvider(id) : null;
|
||||
}
|
||||
|
||||
// TODO: do we want to use react context here?
|
||||
// the main idea was to use native DataTransfer, but it's available only for drag start and drop events
|
||||
// so we need to use a custom store
|
||||
export const globalDnDStore = new DnDStore();
|
||||
@@ -0,0 +1,67 @@
|
||||
import { useId, useMemo, useRef, useState } from 'react';
|
||||
import { DND_STORE_PREFIX, globalDnDStore, type DnDStoreProvider } from './store.js';
|
||||
|
||||
interface IDragOptions {
|
||||
draggable?: boolean;
|
||||
onDrag?: (event: React.DragEvent<HTMLElement>, provider: DnDStoreProvider) => void;
|
||||
onDragStart?: (event: React.DragEvent<HTMLElement>, provider: DnDStoreProvider) => void;
|
||||
onDragEnd?: (event: React.DragEvent<HTMLElement>, provider: DnDStoreProvider) => void;
|
||||
}
|
||||
interface IDrag {
|
||||
isDragging: boolean;
|
||||
props: {
|
||||
draggable?: boolean;
|
||||
onDrag: (event: React.DragEvent<HTMLElement>) => void;
|
||||
onDragStart: (event: React.DragEvent<HTMLElement>) => void;
|
||||
onDragEnd: (event: React.DragEvent<HTMLElement>) => void;
|
||||
};
|
||||
}
|
||||
|
||||
export function useDrag({ draggable, onDragStart, onDrag, onDragEnd }: IDragOptions = {}): IDrag {
|
||||
const id = useId();
|
||||
const [dragging, setDragging] = useState(false);
|
||||
const optionsRef = useRef<IDragOptions>({ draggable, onDragStart, onDrag, onDragEnd });
|
||||
optionsRef.current = { draggable, onDragStart, onDrag, onDragEnd };
|
||||
|
||||
function handleDragStart(event: React.DragEvent<HTMLElement>) {
|
||||
if (!optionsRef.current.draggable) {
|
||||
return;
|
||||
}
|
||||
event.stopPropagation();
|
||||
event.dataTransfer.effectAllowed = 'move';
|
||||
event.dataTransfer.setData(`${DND_STORE_PREFIX}${id}`, id);
|
||||
setDragging(true);
|
||||
optionsRef.current.onDragStart?.(event, globalDnDStore.getProvider(id));
|
||||
}
|
||||
|
||||
function handleDrag(event: React.DragEvent<HTMLElement>) {
|
||||
if (!optionsRef.current.draggable) {
|
||||
return;
|
||||
}
|
||||
optionsRef.current.onDrag?.(event, globalDnDStore.getProvider(id));
|
||||
}
|
||||
|
||||
function handleDragEnd(event: React.DragEvent<HTMLElement>) {
|
||||
if (!optionsRef.current.draggable) {
|
||||
return;
|
||||
}
|
||||
setDragging(false);
|
||||
optionsRef.current.onDragEnd?.(event, globalDnDStore.getProvider(id));
|
||||
globalDnDStore.removeData(id);
|
||||
}
|
||||
|
||||
return {
|
||||
isDragging: dragging,
|
||||
props: {
|
||||
draggable,
|
||||
...useMemo(
|
||||
() => ({
|
||||
onDrag: handleDrag,
|
||||
onDragStart: handleDragStart,
|
||||
onDragEnd: handleDragEnd,
|
||||
}),
|
||||
[],
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
import { useMemo, useRef } from 'react';
|
||||
import { getStoreProvider, type DnDStoreProvider } from './store.js';
|
||||
|
||||
interface IDropOptions {
|
||||
canDrop?: (event: React.DragEvent<HTMLElement>, provider: DnDStoreProvider | null) => boolean;
|
||||
onDrop?: (event: React.DragEvent<HTMLElement>, provider: DnDStoreProvider | null) => void;
|
||||
onDragOver?: (event: React.DragEvent<HTMLElement>, provider: DnDStoreProvider | null) => void;
|
||||
onDragEnter?: (event: React.DragEvent<HTMLElement>, provider: DnDStoreProvider | null) => void;
|
||||
onDragLeave?: (event: React.DragEvent<HTMLElement>, provider: DnDStoreProvider | null) => void;
|
||||
}
|
||||
|
||||
interface IDrop {
|
||||
props: {
|
||||
onDrop: (event: React.DragEvent<HTMLElement>) => void;
|
||||
onDragOver: (event: React.DragEvent<HTMLElement>) => void;
|
||||
onDragEnter: (event: React.DragEvent<HTMLElement>) => void;
|
||||
onDragLeave: (event: React.DragEvent<HTMLElement>) => void;
|
||||
};
|
||||
}
|
||||
|
||||
export function useDrop({ canDrop, onDrop, onDragOver, onDragEnter, onDragLeave }: IDropOptions = {}): IDrop {
|
||||
const optionsRef = useRef<IDropOptions>({ canDrop, onDrop, onDragOver, onDragEnter, onDragLeave });
|
||||
optionsRef.current = { canDrop, onDrop, onDragOver, onDragEnter, onDragLeave };
|
||||
|
||||
function handleOver(event: React.DragEvent<HTMLElement>) {
|
||||
const provider = getStoreProvider(event);
|
||||
const isDroppable = optionsRef.current.canDrop?.(event, provider);
|
||||
if (isDroppable) {
|
||||
event.preventDefault();
|
||||
event.dataTransfer.dropEffect = 'move';
|
||||
} else {
|
||||
event.dataTransfer.dropEffect = 'none';
|
||||
}
|
||||
optionsRef.current.onDragOver?.(event, provider);
|
||||
}
|
||||
|
||||
function handleEnter(event: React.DragEvent<HTMLElement>) {
|
||||
const provider = getStoreProvider(event);
|
||||
optionsRef.current.onDragEnter?.(event, provider);
|
||||
}
|
||||
function handleLeave(event: React.DragEvent<HTMLElement>) {
|
||||
const provider = getStoreProvider(event);
|
||||
optionsRef.current.onDragLeave?.(event, provider);
|
||||
}
|
||||
function handleDrop(event: React.DragEvent<HTMLElement>) {
|
||||
const provider = getStoreProvider(event);
|
||||
optionsRef.current.onDrop?.(event, provider);
|
||||
}
|
||||
|
||||
return {
|
||||
props: useMemo(
|
||||
() => ({
|
||||
onDrop: handleDrop,
|
||||
onDragOver: handleOver,
|
||||
onDragEnter: handleEnter,
|
||||
onDragLeave: handleLeave,
|
||||
}),
|
||||
[],
|
||||
),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": "@dbeaver/tsconfig/tsconfig.webview.json",
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./lib/.tsbuildinfo",
|
||||
"rootDir": "src",
|
||||
"rootDirs": [
|
||||
"src"
|
||||
],
|
||||
"outDir": "lib",
|
||||
"incremental": true,
|
||||
"composite": true
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
||||
@@ -1,2 +1,14 @@
|
||||
import '../src/index.css';
|
||||
import './global.css';
|
||||
import Icons from '../assets/icons/icons.svg?react';
|
||||
|
||||
import type { GlobalProvider } from '@ladle/react';
|
||||
|
||||
export const Provider: GlobalProvider = ({ children }) => {
|
||||
return (
|
||||
<div>
|
||||
<Icons style={{ display: 'none' }} />
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import 'tailwindcss' prefix(tw);
|
||||
@import 'tailwindcss' layer(base) prefix(tw);
|
||||
|
||||
@layer theme {
|
||||
main {
|
||||
@@ -86,6 +86,7 @@
|
||||
|
||||
:root[data-theme='dark'] {
|
||||
--dbv-kit-color-foreground: var(--tw-color-gray-200);
|
||||
--dbv-kit-color-background: var(--tw-color-gray-900);
|
||||
--dbv-kit-btn-loader-base-color: var(--tw-color-gray-900);
|
||||
|
||||
/* Primary Button */
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="cls-1" x="15" y="2" width="2" height="26" />
|
||||
<rect class="cls-1" x="13.21" y="23.28" width="14.14" height="2.02"
|
||||
transform="translate(-11.23 21.46) rotate(-45)" />
|
||||
<rect class="cls-1" x="10.7" y="17.21" width="2.02" height="14.14"
|
||||
transform="translate(-13.74 15.4) rotate(-45)" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 540 B |
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="cls-1" x="11.17" y="2" width="1.67" height="18.33" />
|
||||
<rect class="cls-1" x="9.68" y="16.4" width="11.78" height="1.68"
|
||||
transform="translate(-7.63 16.06) rotate(-45)" />
|
||||
<rect class="cls-1" x="7.59" y="11.35" width="1.68" height="11.79"
|
||||
transform="translate(-9.72 11.01) rotate(-45)" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 546 B |
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="cls-1" x="7.5" y="1" width="1" height="13" />
|
||||
<rect class="cls-1" x="6.61" y="11.35" width="7.07" height="1.01"
|
||||
transform="translate(-5.41 10.64) rotate(-45)" />
|
||||
<rect class="cls-1" x="5.35" y="8.32" width="1.01" height="7.07"
|
||||
transform="translate(-6.67 7.61) rotate(-45)" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 535 B |
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="cls-1" x="15" y="4" width="2" height="26" />
|
||||
<rect class="cls-1" x="4.64" y="6.7" width="14.14" height="2.02"
|
||||
transform="translate(-2.02 10.54) rotate(-45)" />
|
||||
<rect class="cls-1" x="19.28" y=".64" width="2.02" height="14.14"
|
||||
transform="translate(.49 16.6) rotate(-45)" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 532 B |
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="cls-1" x="11.17" y="3.67" width="1.67" height="18.33" />
|
||||
<rect class="cls-1" x="2.54" y="5.92" width="11.78" height="1.68"
|
||||
transform="translate(-2.31 7.94) rotate(-45)" />
|
||||
<rect class="cls-1" x="14.73" y=".87" width="1.68" height="11.79"
|
||||
transform="translate(-.22 12.99) rotate(-45)" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 546 B |
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="cls-1" x="7.5" y="2" width="1" height="13" />
|
||||
<rect class="cls-1" x="2.32" y="3.64" width="7.07" height="1.01"
|
||||
transform="translate(-1.21 5.36) rotate(-45)" />
|
||||
<rect class="cls-1" x="9.64" y=".61" width="1.01" height="7.07"
|
||||
transform="translate(.04 8.39) rotate(-45)" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 530 B |
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-1"
|
||||
d="M5.76,18.69l-2.07,6.28H1.02L7.84,5h3.08l6.82,19.97h-2.76l-2.13-6.28h-7.08ZM12.34,16.68l-1.99-5.75c-.44-1.3-.74-2.49-1.04-3.65h-.06c-.3,1.16-.59,2.4-1.01,3.62l-1.96,5.78h6.05Z" />
|
||||
<path class="cls-1"
|
||||
d="M30.77,21.31c0,1.22.06,2.41.21,3.37h-2.34l-.21-1.77h-.09c-.8,1.1-2.34,2.09-4.39,2.09-2.9,0-4.39-2-4.39-4.04,0-3.4,3.08-5.26,8.62-5.23v-.29c0-1.13-.33-3.25-3.26-3.22-1.36,0-2.76.38-3.76,1.05l-.59-1.71c1.19-.73,2.93-1.22,4.74-1.22,4.39,0,5.45,2.93,5.45,5.72v5.26ZM28.25,17.51c-2.84-.06-6.08.43-6.08,3.17,0,1.68,1.13,2.44,2.43,2.44,1.9,0,3.11-1.16,3.53-2.35.09-.29.12-.58.12-.81v-2.44Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 856 B |
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-1"
|
||||
d="M4.48,14.37l-1.52,4.61h-1.96L6.01,4.31h2.26l5.01,14.67h-2.02l-1.57-4.61h-5.2ZM9.31,12.89l-1.46-4.22c-.33-.96-.54-1.83-.76-2.68h-.04c-.22.85-.44,1.76-.74,2.65l-1.44,4.24h4.44Z" />
|
||||
<path class="cls-1"
|
||||
d="M22.85,16.29c0,.9.04,1.77.15,2.47h-1.72l-.15-1.3h-.07c-.59.81-1.72,1.53-3.22,1.53-2.13,0-3.22-1.47-3.22-2.96,0-2.5,2.26-3.86,6.33-3.84v-.21c0-.83-.24-2.39-2.39-2.37-1,0-2.02.28-2.76.77l-.44-1.26c.87-.53,2.15-.9,3.48-.9,3.22,0,4,2.15,4,4.2v3.86ZM21,13.5c-2.09-.04-4.46.32-4.46,2.32,0,1.24.83,1.79,1.78,1.79,1.39,0,2.29-.85,2.59-1.73.07-.21.09-.43.09-.6v-1.79Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 832 B |
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-1"
|
||||
d="M2.53,9.63l-1.11,3.36H0L3.64,2.32h1.65l3.64,10.67h-1.47l-1.14-3.36h-3.78ZM6.05,8.55l-1.06-3.07c-.24-.7-.4-1.33-.55-1.95h-.03c-.16.62-.32,1.28-.54,1.93l-1.04,3.09h3.23Z" />
|
||||
<path class="cls-1"
|
||||
d="M15.89,11.03c0,.65.03,1.29.11,1.8h-1.25l-.11-.95h-.05c-.43.59-1.25,1.12-2.34,1.12-1.55,0-2.34-1.07-2.34-2.16,0-1.81,1.65-2.81,4.61-2.79v-.15c0-.6-.17-1.74-1.74-1.72-.73,0-1.47.2-2.01.56l-.32-.91c.63-.39,1.57-.65,2.53-.65,2.34,0,2.91,1.57,2.91,3.06v2.81ZM14.54,9c-1.52-.03-3.24.23-3.24,1.69,0,.9.6,1.3,1.3,1.3,1.01,0,1.66-.62,1.88-1.26.05-.15.06-.31.06-.43v-1.3Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 828 B |
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="currentColor">
|
||||
<polygon points="2 10 12 10 7 4 2 10" />
|
||||
<rect x="6" y="6" width="2" height="22" />
|
||||
<rect x="14" y="6" width="16" height="2" />
|
||||
<rect x="14" y="15" width="12" height="2" />
|
||||
<rect x="14" y="24" width="8" height="2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 353 B |
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
||||
<polygon points="2 8.14 9.14 8.14 5.57 3.86 2 8.14" />
|
||||
<rect x="4.86" y="5.29" width="1.43" height="15.71" />
|
||||
<rect x="10.57" y="5.29" width="11.43" height="1.43" />
|
||||
<rect x="10.57" y="11.71" width="8.57" height="1.43" />
|
||||
<rect x="10.57" y="18.14" width="5.71" height="1.43" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 414 B |
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor">
|
||||
<polygon points="0 4 5 4 2.5 1 0 4" />
|
||||
<rect x="2" y="4" width="1" height="11" />
|
||||
<rect x="6" y="3" width="10" height="1" />
|
||||
<rect x="6" y="8" width="7" height="1" />
|
||||
<rect x="6" y="13" width="4" height="1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 346 B |
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="currentColor">
|
||||
<polygon points="12 22 2 22 7 28 12 22" />
|
||||
<rect x="6" y="4" width="2" height="22" />
|
||||
<rect x="14" y="6" width="16" height="2" />
|
||||
<rect x="14" y="15" width="12" height="2" />
|
||||
<rect x="14" y="24" width="8" height="2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 355 B |
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
||||
<polygon points="9.14 16.71 2 16.71 5.57 21 9.14 16.71" />
|
||||
<rect x="4.86" y="3.86" width="1.43" height="15.71" />
|
||||
<rect x="10.57" y="5.29" width="11.43" height="1.43" />
|
||||
<rect x="10.57" y="11.71" width="8.57" height="1.43" />
|
||||
<rect x="10.57" y="18.14" width="5.71" height="1.43" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 418 B |
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor">
|
||||
<polygon points="5 12 0 12 2.5 15 5 12" />
|
||||
<rect x="2" y="1" width="1" height="12" />
|
||||
<rect x="6" y="3" width="10" height="1" />
|
||||
<rect x="6" y="8" width="7" height="1" />
|
||||
<rect x="6" y="13" width="4" height="1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 350 B |
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="currentColor">
|
||||
<polygon points="4 10 14 10 9 4 4 10" />
|
||||
<rect x="8" y="6" width="2" height="22" />
|
||||
<polygon points="28 22 18 22 23 28 28 22" />
|
||||
<rect x="22" y="4" width="2" height="22" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 307 B |
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
||||
<polygon points="3.4 8.29 10.55 8.29 6.98 4 3.4 8.29" />
|
||||
<rect x="6.26" y="5.43" width="1.43" height="15.71" />
|
||||
<polygon points="20.55 16.86 13.4 16.86 16.98 21.14 20.55 16.86" />
|
||||
<rect x="16.26" y="4" width="1.43" height="15.71" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 367 B |
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor">
|
||||
<polygon points="2 4 7 4 4.5 1 2 4" />
|
||||
<rect x="4" y="4" width="1" height="11" />
|
||||
<polygon points="14 12 9 12 11.5 15 14 12" />
|
||||
<rect x="11" y="1" width="1" height="11" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 306 B |
@@ -0,0 +1,302 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- SORTING ICONS -->
|
||||
<symbol id="icon-sort-unknown" viewBox="0 0 32 32" fill="currentColor">
|
||||
<polygon points="4 10 14 10 9 4 4 10" />
|
||||
<rect x="8" y="6" width="2" height="22" />
|
||||
<polygon points="28 22 18 22 23 28 28 22" />
|
||||
<rect x="22" y="4" width="2" height="22" />
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-sort-unknown_m" viewBox="0 0 24 24" fill="currentColor">
|
||||
<polygon points="3.4 8.29 10.55 8.29 6.98 4 3.4 8.29" />
|
||||
<rect x="6.26" y="5.43" width="1.43" height="15.71" />
|
||||
<polygon points="20.55 16.86 13.4 16.86 16.98 21.14 20.55 16.86" />
|
||||
<rect x="16.26" y="4" width="1.43" height="15.71" />
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-sort-unknown_sm" viewBox="0 0 16 16" fill="currentColor">
|
||||
<polygon points="2 4 7 4 4.5 1 2 4" />
|
||||
<rect x="4" y="4" width="1" height="11" />
|
||||
<polygon points="14 12 9 12 11.5 15 14 12" />
|
||||
<rect x="11" y="1" width="1" height="11" />
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-sort-desc" viewBox="0 0 32 32"
|
||||
fill="currentColor">
|
||||
<polygon points="12 22 2 22 7 28 12 22" />
|
||||
<rect x="6" y="4" width="2" height="22" />
|
||||
<rect x="14" y="6" width="16" height="2" />
|
||||
<rect x="14" y="15" width="12" height="2" />
|
||||
<rect x="14" y="24" width="8" height="2" />
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-sort-desc_m" viewBox="0 0 24 24"
|
||||
fill="currentColor">
|
||||
<polygon points="9.14 16.71 2 16.71 5.57 21 9.14 16.71" />
|
||||
<rect x="4.86" y="3.86" width="1.43" height="15.71" />
|
||||
<rect x="10.57" y="5.29" width="11.43" height="1.43" />
|
||||
<rect x="10.57" y="11.71" width="8.57" height="1.43" />
|
||||
<rect x="10.57" y="18.14" width="5.71" height="1.43" />
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-sort-desc_sm" viewBox="0 0 16 16"
|
||||
fill="currentColor">
|
||||
<polygon points="5 12 0 12 2.5 15 5 12" />
|
||||
<rect x="2" y="1" width="1" height="12" />
|
||||
<rect x="6" y="3" width="10" height="1" />
|
||||
<rect x="6" y="8" width="7" height="1" />
|
||||
<rect x="6" y="13" width="4" height="1" />
|
||||
</symbol>
|
||||
|
||||
|
||||
<symbol id="icon-sort-asc" viewBox="0 0 32 32" fill="currentColor">
|
||||
<polygon points="2 10 12 10 7 4 2 10" />
|
||||
<rect x="6" y="6" width="2" height="22" />
|
||||
<rect x="14" y="6" width="16" height="2" />
|
||||
<rect x="14" y="15" width="12" height="2" />
|
||||
<rect x="14" y="24" width="8" height="2" />
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-sort-asc_m" viewBox="0 0 24 24" fill="currentColor">
|
||||
<polygon points="2 8.14 9.14 8.14 5.57 3.86 2 8.14" />
|
||||
<rect x="4.86" y="5.29" width="1.43" height="15.71" />
|
||||
<rect x="10.57" y="5.29" width="11.43" height="1.43" />
|
||||
<rect x="10.57" y="11.71" width="8.57" height="1.43" />
|
||||
<rect x="10.57" y="18.14" width="5.71" height="1.43" />
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-sort-asc_sm" viewBox="0 0 16 16" fill="currentColor">
|
||||
<polygon points="0 4 5 4 2.5 1 0 4" />
|
||||
<rect x="2" y="4" width="1" height="11" />
|
||||
<rect x="6" y="3" width="10" height="1" />
|
||||
<rect x="6" y="8" width="7" height="1" />
|
||||
<rect x="6" y="13" width="4" height="1" />
|
||||
</symbol>
|
||||
<!-- SORTING ICONS END -->
|
||||
|
||||
<!-- CROSS ICON (ONLY ONE SIZE)-->
|
||||
<symbol id="icon-cross_m" viewBox="0 0 24 24">
|
||||
<path xmlns="http://www.w3.org/2000/svg" fill="currentColor" fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M3.31579 3.31579C2.89474 3.73684 2.89474 4.42105 3.31579 4.84211L10.4737 12L3.31579 19.1579C2.89474 19.5789 2.89474 20.2632 3.31579 20.6842C3.73684 21.1053 4.42105 21.1053 4.84211 20.6842L12 13.5263L19.1579 20.6842C19.5789 21.1053 20.2632 21.1053 20.6842 20.6842C21.1053 20.2632 21.1053 19.5789 20.6842 19.1579L13.5263 12L20.6842 4.84211C21.1053 4.42105 21.1053 3.73684 20.6842 3.31579C20.2632 2.89474 19.5789 2.89474 19.1579 3.31579L12 10.4737L4.84211 3.31579C4.42105 2.89474 3.73684 2.89474 3.31579 3.31579Z" />
|
||||
</symbol>
|
||||
<!-- CROSS ICON END -->
|
||||
|
||||
<!-- REPLACE ICONS -->
|
||||
<symbol id="icon-replace_sm" viewBox="0 0 16 16" fill="currentColor">
|
||||
<path
|
||||
d="M10.03,1h1.04v2.39h.02c.24-.42.68-.69,1.3-.69.95,0,1.61.79,1.61,1.93,0,1.36-.86,2.04-1.71,2.04-.55,0-.99-.21-1.28-.71h-.02l-.04.62h-.95c.02-.26.03-.64.03-.98V1ZM11.06,4.97c0,.07,0,.13.03.19.11.37.48.62.93.62.65,0,1.03-.45,1.03-1.12,0-.59-.35-1.09-1.02-1.09-.41,0-.81.25-.93.65-.02.07-.04.14-.04.22v.52Z" />
|
||||
<path
|
||||
d="M8.99,13.78c-.18.09-.58.22-1.09.22-1.15,0-1.89-.78-1.89-1.94s.8-2.03,2.04-2.03c.41,0,.77.1.96.2v.82c-.17-.09-.58-.23-.96-.23-.59,0-1.04.4-1.04,1.19,0,.88.51,1.13,1.02,1.13.39,0,.77-.08.97-.17v.8Z" />
|
||||
<path d="M13,9v6H3v-6h10M14,8H2v8h12V8h0Z" />
|
||||
<path
|
||||
d="M5,5h-1v-1.49c0-1.38,1.13-2.51,2.51-2.51h2.49v1h-2.49c-.83,0-1.51.68-1.51,1.51v1.49Z" />
|
||||
<polygon points="4.5 6 3 4 6 4 4.5 6" />
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-replace_m" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path
|
||||
d="M15.62.88h1.64v3.75h.02c.38-.67,1.07-1.09,2.04-1.09,1.49,0,2.53,1.24,2.53,3.04,0,2.14-1.36,3.2-2.69,3.2-.86,0-1.56-.33-2.01-1.11h-.02l-.06.98h-1.49c.02-.41.05-1.01.05-1.54V.88ZM17.23,7.12c0,.1.01.21.04.3.18.58.75.98,1.46.98,1.03,0,1.62-.71,1.62-1.77,0-.92-.55-1.71-1.6-1.71-.65,0-1.27.4-1.47,1.03-.03.1-.06.22-.06.35v.82Z" />
|
||||
<path
|
||||
d="M13.98,19.4c-.28.14-.91.35-1.72.35-1.8,0-2.98-1.22-2.98-3.05s1.26-3.19,3.21-3.19c.64,0,1.21.16,1.51.32v1.29c-.27-.14-.91-.36-1.51-.36-.93,0-1.64.64-1.64,1.87,0,1.38.81,1.77,1.6,1.77.62,0,1.21-.13,1.52-.26v1.26Z" />
|
||||
<path d="M20.29,11.88v9.43H4.57v-9.43h15.71M21.86,10.31H3v12.57h18.86v-12.57h0Z" />
|
||||
<path
|
||||
d="M7.71,7.17h-1.57v-2.34c0-2.18,1.77-3.95,3.95-3.95h3.91v1.57h-3.91c-1.31,0-2.37,1.07-2.37,2.37v2.34Z" />
|
||||
<polygon points="6.93 8.74 4.57 5.6 9.29 5.6 6.93 8.74" />
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-replace" viewBox="0 0 32 32" fill="currentColor">
|
||||
<path
|
||||
d="M20.06,2h2.09v4.78h.03c.49-.85,1.37-1.38,2.59-1.38,1.9,0,3.22,1.57,3.22,3.87,0,2.72-1.73,4.07-3.43,4.07-1.1,0-1.98-.42-2.56-1.41h-.03l-.08,1.24h-1.9c.03-.52.06-1.29.06-1.96V2ZM22.11,9.94c0,.13.01.27.06.39.22.74.95,1.24,1.85,1.24,1.3,0,2.06-.91,2.06-2.25,0-1.17-.7-2.17-2.03-2.17-.83,0-1.61.51-1.87,1.3-.04.13-.07.28-.07.45v1.04Z" />
|
||||
<path
|
||||
d="M17.97,25.56c-.36.17-1.16.44-2.19.44-2.3,0-3.79-1.56-3.79-3.88s1.6-4.06,4.09-4.06c.82,0,1.54.2,1.92.41v1.65c-.34-.17-1.16-.46-1.92-.46-1.19,0-2.09.81-2.09,2.38,0,1.76,1.03,2.25,2.04,2.25.79,0,1.54-.16,1.94-.33v1.6Z" />
|
||||
<path d="M26,16v12H6v-12h20M28,14H4v16h24V14h0Z" />
|
||||
<path
|
||||
d="M10,10h-2v-2.98c0-2.77,2.25-5.02,5.02-5.02h4.98v2h-4.98c-1.67,0-3.02,1.36-3.02,3.02v2.98Z" />
|
||||
<polygon points="9 12 6 8 12 8 9 12" />
|
||||
</symbol>
|
||||
<!-- REPLACE ICONS END -->
|
||||
|
||||
<!-- REPLACE ALL ICONS -->
|
||||
<symbol id="icon-replace-all" viewBox="0 0 32 32" fill="currentColor">
|
||||
<path
|
||||
d="M13,24.99c0,.67-.03,1.49.05,2.01h-1.25l-.11-1.14h-.05c-.43.6-1.25,1.14-2.34,1.14-1.55,0-2.34-1.09-2.34-2.2,0-1.85,1.65-2.87,4.61-2.85v-.16c0-.62-.17-1.33-1.74-1.31-.73,0-1.47.3-2.01.66l-.79-1.19c.63-.4,2.05-.95,3.01-.95,2.34,0,2.98,1.6,2.98,3.12v2.87ZM11.59,23.14c-1.21-.03-3.03.19-3.03,1.38,0,.73.39,1.06,1.48,1.06.81,0,1.33-.51,1.51-1.02.04-.13.05-.25.05-.35v-1.06Z" />
|
||||
<path
|
||||
d="M22.05,8.99c0,.67-.03,1.49.05,2.01h-1.25l-.11-1.14h-.05c-.43.6-1.25,1.14-2.34,1.14-1.55,0-2.34-1.09-2.34-2.2,0-1.85,1.65-2.87,4.61-2.85v-.16c0-.62-.17-1.33-1.74-1.31-.73,0-1.47.3-2.01.66l-.79-1.19c.63-.4,2.05-.95,3.01-.95,2.34,0,2.98,1.6,2.98,3.12v2.87ZM20.64,7.14c-1.21-.03-3.03.19-3.03,1.38,0,.73.39,1.06,1.48,1.06.81,0,1.33-.51,1.51-1.02.04-.13.05-.25.05-.35v-1.06Z" />
|
||||
<path
|
||||
d="M23.06,1.07h1.83v4.33h.03c.43-.77,1.2-1.25,2.27-1.25,1.66,0,2.82,1.42,2.82,3.5,0,2.46-1.51,3.69-3,3.69-.96,0-1.73-.38-2.24-1.28h-.03l-.07,1.12h-1.66c.03-.47.06-1.17.06-1.78V1.07ZM24.85,8.26c0,.12.01.24.05.35.2.67.84,1.13,1.62,1.13,1.14,0,1.8-.82,1.8-2.03,0-1.06-.61-1.97-1.78-1.97-.72,0-1.41.46-1.63,1.18-.04.12-.06.25-.06.4v.94Z" />
|
||||
<path
|
||||
d="M20.97,26.56c-.36.17-1.16.44-2.19.44-2.3,0-3.79-1.56-3.79-3.88s1.6-4.06,4.09-4.06c.82,0,1.54.2,1.92.41v1.65c-.34-.17-1.16-.46-1.92-.46-1.19,0-2.09.77-2.09,2.34,0,1.76,1.03,2.29,2.04,2.29.79,0,1.54-.16,1.94-.33v1.6Z" />
|
||||
<path d="M24,18v10H4v-10h20M26,16H2v14h24v-14h0Z" />
|
||||
<polygon points="9 12 9 14 28 14 28 28 30 28 30 12 9 12" />
|
||||
<g>
|
||||
<path
|
||||
d="M6,13h-2v-2.98c0-2.77,2.25-5.02,5.02-5.02h4.98v2h-4.98c-1.67,0-3.02,1.36-3.02,3.02v2.98Z" />
|
||||
<polygon points="5 15 2 11 8 11 5 15" />
|
||||
</g>
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-replace-all_m" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path
|
||||
d="M9.25,19.01c0,.5-.02,1.12.04,1.51h-.94l-.08-.86h-.04c-.32.45-.94.86-1.76.86-1.16,0-1.76-.82-1.76-1.65,0-1.39,1.24-2.15,3.46-2.14v-.12c0-.46-.13-1-1.31-.98-.55,0-1.1.22-1.51.5l-.6-.89c.48-.3,1.53-.71,2.26-.71,1.76,0,2.23,1.2,2.23,2.34v2.15ZM8.19,17.63c-.91-.02-2.28.14-2.28,1.03,0,.55.29.8,1.11.8.61,0,1-.38,1.13-.77.03-.09.04-.19.04-.27v-.8Z" />
|
||||
<path
|
||||
d="M16.04,7.01c0,.5-.02,1.12.04,1.51h-.94l-.08-.86h-.04c-.32.45-.94.86-1.76.86-1.16,0-1.76-.82-1.76-1.65,0-1.39,1.24-2.15,3.46-2.14v-.12c0-.46-.13-1-1.31-.98-.55,0-1.1.22-1.51.5l-.6-.89c.48-.3,1.53-.71,2.26-.71,1.76,0,2.23,1.2,2.23,2.34v2.15ZM14.98,5.63c-.91-.02-2.28.14-2.28,1.03,0,.55.29.8,1.11.8.61,0,1-.38,1.13-.77.03-.09.04-.19.04-.27v-.8Z" />
|
||||
<path
|
||||
d="M16.79,1.07h1.37v3.24h.02c.32-.58.9-.94,1.7-.94,1.25,0,2.12,1.07,2.12,2.63,0,1.85-1.13,2.76-2.25,2.76-.72,0-1.3-.29-1.68-.96h-.02l-.05.84h-1.25c.02-.35.04-.88.04-1.33V1.07ZM18.14,6.46c0,.09,0,.18.04.26.15.5.63.84,1.22.84.86,0,1.35-.61,1.35-1.53,0-.8-.46-1.48-1.34-1.48-.54,0-1.06.34-1.22.89-.03.09-.05.19-.05.3v.7Z" />
|
||||
<path
|
||||
d="M15.23,20.19c-.27.13-.87.33-1.64.33-1.72,0-2.84-1.17-2.84-2.91s1.2-3.04,3.07-3.04c.61,0,1.16.15,1.44.31v1.23c-.25-.13-.87-.34-1.44-.34-.89,0-1.57.58-1.57,1.76,0,1.32.77,1.72,1.53,1.72.59,0,1.16-.12,1.45-.25v1.2Z" />
|
||||
<path d="M17.5,13.77v7.5H2.5v-7.5h15M19,12.27H1v10.5h18v-10.5h0Z" />
|
||||
<polygon
|
||||
points="6.25 9.27 6.25 10.77 20.5 10.77 20.5 21.27 22 21.27 22 9.27 6.25 9.27" />
|
||||
<g>
|
||||
<path
|
||||
d="M4,10.02h-1.5v-2.23c0-2.08,1.69-3.77,3.77-3.77h3.73v1.5h-3.73c-1.25,0-2.27,1.02-2.27,2.27v2.23Z" />
|
||||
<polygon points="3.25 11.52 1 8.52 5.5 8.52 3.25 11.52" />
|
||||
</g>
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-replace-all_sm" viewBox="0 0 16 16" fill="currentColor">
|
||||
<path
|
||||
d="M6.5,13.49c0,.33-.01.74.02,1.01h-.63l-.06-.57h-.02c-.21.3-.63.57-1.17.57-.78,0-1.17-.55-1.17-1.1,0-.93.82-1.43,2.3-1.43v-.08c0-.31-.09-.66-.87-.66-.36,0-.74.15-1.01.33l-.4-.59c.32-.2,1.02-.48,1.51-.48,1.17,0,1.49.8,1.49,1.56v1.43ZM5.8,12.57c-.61-.01-1.52.09-1.52.69,0,.37.19.53.74.53.4,0,.66-.25.75-.51.02-.06.03-.13.03-.18v-.53Z" />
|
||||
<path
|
||||
d="M11.02,4.49c0,.33-.01.74.02,1.01h-.63l-.06-.57h-.02c-.21.3-.63.57-1.17.57-.78,0-1.17-.55-1.17-1.1,0-.93.82-1.43,2.3-1.43v-.08c0-.31-.09-.66-.87-.66-.36,0-.74.15-1.01.33l-.4-.59c.32-.2,1.02-.48,1.51-.48,1.17,0,1.49.8,1.49,1.56v1.43ZM10.32,3.57c-.61-.01-1.52.09-1.52.69,0,.37.19.53.74.53.4,0,.66-.25.75-.51.02-.06.03-.13.03-.18v-.53Z" />
|
||||
<path
|
||||
d="M11.53.54h.91v2.16h.01c.21-.38.6-.63,1.13-.63.83,0,1.41.71,1.41,1.75,0,1.23-.76,1.84-1.5,1.84-.48,0-.87-.19-1.12-.64h-.01l-.03.56h-.83c.01-.23.03-.58.03-.89V.54ZM12.43,4.13c0,.06,0,.12.02.17.1.33.42.56.81.56.57,0,.9-.41.9-1.02,0-.53-.31-.98-.89-.98-.36,0-.71.23-.82.59-.02.06-.03.13-.03.2v.47Z" />
|
||||
<path
|
||||
d="M10.48,14.28c-.18.09-.58.22-1.09.22-1.15,0-1.89-.78-1.89-1.94s.8-2.03,2.04-2.03c.41,0,.77.1.96.2v.82c-.17-.09-.58-.23-.96-.23-.59,0-1.04.38-1.04,1.17,0,.88.51,1.15,1.02,1.15.39,0,.77-.08.97-.17v.8Z" />
|
||||
<path d="M12,10v5H2v-5h10M13,9H1v7h12v-7h0Z" />
|
||||
<polygon points="4.5 7 4.5 8 14 8 14 15 15 15 15 7 4.5 7" />
|
||||
<g>
|
||||
<path
|
||||
d="M3,7h-1v-1.49c0-1.38,1.13-2.51,2.51-2.51h2.49v1h-2.49c-.83,0-1.51.68-1.51,1.51v1.49Z" />
|
||||
<polygon points="2.5 8 1 6 4 6 2.5 8" />
|
||||
</g>
|
||||
</symbol>
|
||||
<!-- REPLACE ALL ICONS END -->
|
||||
|
||||
<!-- REGEX ICONS -->
|
||||
<symbol id="icon-regex" viewBox="0 0 32 32" fill="currentColor">
|
||||
<rect x="20.04" y="2" width="2" height="22" />
|
||||
<rect x="20.04" y="2" width="2" height="22"
|
||||
transform="translate(-.9 24.42) rotate(-59.21)" />
|
||||
<rect x="10.04" y="12" width="22" height="2"
|
||||
transform="translate(-3.69 13.25) rotate(-32.29)" />
|
||||
<rect x="2.04" y="22" width="8" height="8" />
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-regex_m" viewBox="0 0 24 24" fill="currentColor">
|
||||
<rect x="14.46" y="2" width="1.38" height="15.14" />
|
||||
<rect x="14.46" y="2" width="1.38" height="15.14"
|
||||
transform="translate(-.83 17.68) rotate(-59.21)" />
|
||||
<rect x="7.58" y="8.88" width="15.14" height="1.38"
|
||||
transform="translate(-2.77 9.57) rotate(-32.29)" />
|
||||
<rect x="2.08" y="16.5" width="5.5" height="5.5" />
|
||||
</symbol>
|
||||
<symbol id="icon-regex_sm" viewBox="0 0 16 16" fill="currentColor">
|
||||
<rect x="10" y="1" width="1" height="11" />
|
||||
<rect x="10" y="1" width="1" height="11"
|
||||
transform="translate(-.46 12.19) rotate(-59.21)" />
|
||||
<rect x="5" y="6" width="11" height="1"
|
||||
transform="translate(-1.85 6.61) rotate(-32.29)" />
|
||||
<rect x="1" y="11" width="4" height="4" />
|
||||
</symbol>
|
||||
<!-- REGEX ICONS END -->
|
||||
|
||||
<!-- MATCH WORD ICONS -->
|
||||
<symbol id="icon-match-word" viewBox="0 0 32 32" fill="currentColor">
|
||||
<path
|
||||
d="M13.82,20.03c0,1.12.05,2.22.18,3.1h-2.01l-.18-1.63h-.08c-.69,1.02-2.01,1.92-3.76,1.92-2.49,0-3.76-1.84-3.76-3.71,0-3.13,2.64-4.84,7.4-4.81v-.27c0-1.04-.28-2.99-2.8-2.97-1.17,0-2.36.35-3.23.96l-.51-1.58c1.02-.67,2.52-1.12,4.07-1.12,3.76,0,4.68,2.7,4.68,5.26v4.84ZM11.66,16.53c-2.44-.05-5.21.4-5.21,2.91,0,1.55.97,2.24,2.08,2.24,1.63,0,2.67-1.07,3.02-2.16.08-.27.1-.53.1-.75v-2.24Z" />
|
||||
<path
|
||||
d="M17.11,5h2.44v7.28h-.75c.87-1.44,2.44-2.35,4.62-2.35,3.39,0,5.75,2.67,5.75,6.57,0,4.62-3.08,6.92-6.11,6.92-1.96,0-2.72-.72-3.76-2.4h-.3l.1,2.11h-2.1c.06-.88.11-2.19.11-3.34V5ZM19.38,17.94c0,.29.08.59.17.85.45,1.63,1.21,2.75,3,2.75,2.61,0,4.12-2,4.12-4.97,0-2.59-1.4-4.81-4.06-4.81-1.65,0-2.55,1.12-3.06,2.89-.08.29-.17.61-.17.99v2.3Z" />
|
||||
<rect x="1" y="23" width="2" height="4" />
|
||||
<rect x="29" y="23" width="2" height="4" />
|
||||
<rect x="1.67" y="25" width="29.33" height="2" />
|
||||
</symbol>
|
||||
<symbol id="icon-match-word_m" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path
|
||||
d="M10.41,14.93c0,.82.04,1.61.13,2.25h-1.47l-.13-1.18h-.06c-.5.74-1.47,1.4-2.76,1.4-1.83,0-2.76-1.34-2.76-2.7,0-2.27,1.94-3.52,5.43-3.5v-.19c0-.76-.2-2.18-2.05-2.16-.86,0-1.73.25-2.37.7l-.37-1.15c.75-.49,1.85-.82,2.98-.82,2.76,0,3.43,1.96,3.43,3.83v3.52ZM8.82,12.38c-1.79-.04-3.82.29-3.82,2.12,0,1.13.71,1.63,1.53,1.63,1.19,0,1.96-.78,2.22-1.57.06-.19.07-.39.07-.54v-1.63Z" />
|
||||
<path
|
||||
d="M12.82,4h1.79v5.29h-.55c.64-1.05,1.79-1.71,3.39-1.71,2.49,0,4.21,1.94,4.21,4.78,0,3.36-2.26,5.03-4.48,5.03-1.44,0-2-.52-2.76-1.75h-.22l.08,1.54h-1.54c.04-.64.08-1.59.08-2.43V4ZM14.49,13.41c0,.21.06.43.12.62.33,1.19.89,2,2.2,2,1.91,0,3.02-1.46,3.02-3.61,0-1.88-1.03-3.5-2.98-3.5-1.21,0-1.87.82-2.24,2.1-.06.21-.12.45-.12.72v1.67Z" />
|
||||
<rect x="1" y="17" width="1.47" height="3" />
|
||||
<rect x="21.54" y="17" width="1.47" height="3" />
|
||||
<rect x="1.49" y="18.55" width="21.52" height="1.45" />
|
||||
</symbol>
|
||||
<symbol id="icon-match-word_sm" viewBox="0 0 16 16" fill="currentColor">
|
||||
<path
|
||||
d="M6.9,10.2c0,.61.03,1.21.1,1.69h-1.15l-.1-.89h-.04c-.39.55-1.15,1.05-2.16,1.05-1.43,0-2.16-1.01-2.16-2.03,0-1.71,1.52-2.64,4.24-2.62v-.15c0-.57-.16-1.63-1.6-1.62-.67,0-1.35.19-1.85.52l-.29-.86c.58-.36,1.44-.61,2.33-.61,2.16,0,2.68,1.47,2.68,2.87v2.64ZM5.66,8.29c-1.4-.03-2.99.22-2.99,1.59,0,.85.55,1.22,1.19,1.22.93,0,1.53-.58,1.73-1.18.04-.15.06-.29.06-.41v-1.22Z" />
|
||||
<path
|
||||
d="M8.73,2h1.27v3.97h-.39c.45-.79,1.27-1.28,2.4-1.28,1.76,0,2.99,1.46,2.99,3.58,0,2.52-1.6,3.77-3.18,3.77-1.02,0-1.42-.39-1.95-1.31h.13l-.23,1.15h-1.09c.03-.48.06-1.19.06-1.82V2ZM9.93,9.06c0,.16.01.32.06.47.23.89.64,1.5,1.58,1.5,1.35,0,2.14-1.09,2.14-2.71,0-1.41-.73-2.62-2.11-2.62-.86,0-1.33.61-1.59,1.57-.04.16-.07.33-.07.54v1.25Z" />
|
||||
|
||||
<rect y="12" width="1" height="2" />
|
||||
<rect x="15" y="12.02" width="1" height="1.98" />
|
||||
<rect y="13" width="16" height="1" />
|
||||
</symbol>
|
||||
<!-- MATCH WORD ICONS END -->
|
||||
|
||||
<!-- CASE ICONS -->
|
||||
<symbol id="icon-case" viewBox="0 0 32 32" fill="currentColor">
|
||||
<path
|
||||
d="M5.76,18.69l-2.07,6.28H1.02L7.84,5h3.08l6.82,19.97h-2.76l-2.13-6.28h-7.08ZM12.34,16.68l-1.99-5.75c-.44-1.3-.74-2.49-1.04-3.65h-.06c-.3,1.16-.59,2.4-1.01,3.62l-1.96,5.78h6.05Z" />
|
||||
<path
|
||||
d="M30.77,21.31c0,1.22.06,2.41.21,3.37h-2.34l-.21-1.77h-.09c-.8,1.1-2.34,2.09-4.39,2.09-2.9,0-4.39-2-4.39-4.04,0-3.4,3.08-5.26,8.62-5.23v-.29c0-1.13-.33-3.25-3.26-3.22-1.36,0-2.76.38-3.76,1.05l-.59-1.71c1.19-.73,2.93-1.22,4.74-1.22,4.39,0,5.45,2.93,5.45,5.72v5.26ZM28.25,17.51c-2.84-.06-6.08.43-6.08,3.17,0,1.68,1.13,2.44,2.43,2.44,1.9,0,3.11-1.16,3.53-2.35.09-.29.12-.58.12-.81v-2.44Z" />
|
||||
</symbol>
|
||||
<symbol id="icon-case_m" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path
|
||||
d="M4.48,14.37l-1.52,4.61h-1.96L6.01,4.31h2.26l5.01,14.67h-2.02l-1.57-4.61h-5.2ZM9.31,12.89l-1.46-4.22c-.33-.96-.54-1.83-.76-2.68h-.04c-.22.85-.44,1.76-.74,2.65l-1.44,4.24h4.44Z" />
|
||||
<path
|
||||
d="M22.85,16.29c0,.9.04,1.77.15,2.47h-1.72l-.15-1.3h-.07c-.59.81-1.72,1.53-3.22,1.53-2.13,0-3.22-1.47-3.22-2.96,0-2.5,2.26-3.86,6.33-3.84v-.21c0-.83-.24-2.39-2.39-2.37-1,0-2.02.28-2.76.77l-.44-1.26c.87-.53,2.15-.9,3.48-.9,3.22,0,4,2.15,4,4.2v3.86ZM21,13.5c-2.09-.04-4.46.32-4.46,2.32,0,1.24.83,1.79,1.78,1.79,1.39,0,2.29-.85,2.59-1.73.07-.21.09-.43.09-.6v-1.79Z" />
|
||||
</symbol>
|
||||
<symbol id="icon-case_sm" viewBox="0 0 16 16" fill="currentColor">
|
||||
<path
|
||||
d="M2.53,9.63l-1.11,3.36H0L3.64,2.32h1.65l3.64,10.67h-1.47l-1.14-3.36h-3.78ZM6.05,8.55l-1.06-3.07c-.24-.7-.4-1.33-.55-1.95h-.03c-.16.62-.32,1.28-.54,1.93l-1.04,3.09h3.23Z" />
|
||||
<path
|
||||
d="M15.89,11.03c0,.65.03,1.29.11,1.8h-1.25l-.11-.95h-.05c-.43.59-1.25,1.12-2.34,1.12-1.55,0-2.34-1.07-2.34-2.16,0-1.81,1.65-2.81,4.61-2.79v-.15c0-.6-.17-1.74-1.74-1.72-.73,0-1.47.2-2.01.56l-.32-.91c.63-.39,1.57-.65,2.53-.65,2.34,0,2.91,1.57,2.91,3.06v2.81ZM14.54,9c-1.52-.03-3.24.23-3.24,1.69,0,.9.6,1.3,1.3,1.3,1.01,0,1.66-.62,1.88-1.26.05-.15.06-.31.06-.43v-1.3Z" />
|
||||
</symbol>
|
||||
<!-- CASE ICONS END -->
|
||||
|
||||
<!-- ARROW ICONS-->
|
||||
<symbol id="icon-arrow-up" viewBox="0 0 32 32" fill="currentColor">
|
||||
<rect x="15" y="4" width="2" height="26" />
|
||||
<rect x="4.64" y="6.7" width="14.14" height="2.02"
|
||||
transform="translate(-2.02 10.54) rotate(-45)" />
|
||||
<rect x="19.28" y=".64" width="2.02" height="14.14"
|
||||
transform="translate(.49 16.6) rotate(-45)" />
|
||||
</symbol>
|
||||
<symbol id="icon-arrow-up_m" viewBox="0 0 24 24" fill="currentColor">
|
||||
<rect x="11.17" y="3.67" width="1.67" height="18.33" />
|
||||
<rect x="2.54" y="5.92" width="11.78" height="1.68"
|
||||
transform="translate(-2.31 7.94) rotate(-45)" />
|
||||
<rect x="14.73" y=".87" width="1.68" height="11.79"
|
||||
transform="translate(-.22 12.99) rotate(-45)" />
|
||||
</symbol>
|
||||
<symbol id="icon-arrow-up_sm" viewBox="0 0 16 16" fill="currentColor">
|
||||
<rect x="7.5" y="2" width="1" height="13" />
|
||||
<rect x="2.32" y="3.64" width="7.07" height="1.01"
|
||||
transform="translate(-1.21 5.36) rotate(-45)" />
|
||||
<rect x="9.64" y=".61" width="1.01" height="7.07"
|
||||
transform="translate(.04 8.39) rotate(-45)" />
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-arrow-down" viewBox="0 0 32 32" fill="currentColor">
|
||||
<rect x="15" y="2" width="2" height="26" />
|
||||
<rect x="13.21" y="23.28" width="14.14" height="2.02"
|
||||
transform="translate(-11.23 21.46) rotate(-45)" />
|
||||
<rect x="10.7" y="17.21" width="2.02" height="14.14"
|
||||
transform="translate(-13.74 15.4) rotate(-45)" />
|
||||
</symbol>
|
||||
<symbol id="icon-arrow-down_m" viewBox="0 0 24 24" fill="currentColor">
|
||||
<rect x="11.17" y="2" width="1.67" height="18.33" />
|
||||
<rect x="9.68" y="16.4" width="11.78" height="1.68"
|
||||
transform="translate(-7.63 16.06) rotate(-45)" />
|
||||
<rect x="7.59" y="11.35" width="1.68" height="11.79"
|
||||
transform="translate(-9.72 11.01) rotate(-45)" />
|
||||
</symbol>
|
||||
<symbol id="icon-arrow-down_sm" viewBox="0 0 16 16" fill="currentColor">
|
||||
<rect x="7.5" y="1" width="1" height="13" />
|
||||
<rect x="6.61" y="11.35" width="7.07" height="1.01"
|
||||
transform="translate(-5.41 10.64) rotate(-45)" />
|
||||
<rect x="5.35" y="8.32" width="1.01" height="7.07"
|
||||
transform="translate(-6.67 7.61) rotate(-45)" />
|
||||
</symbol>
|
||||
<!-- ARROW ICONS END -->
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 21 KiB |
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-1"
|
||||
d="M13.82,20.03c0,1.12.05,2.22.18,3.1h-2.01l-.18-1.63h-.08c-.69,1.02-2.01,1.92-3.76,1.92-2.49,0-3.76-1.84-3.76-3.71,0-3.13,2.64-4.84,7.4-4.81v-.27c0-1.04-.28-2.99-2.8-2.97-1.17,0-2.36.35-3.23.96l-.51-1.58c1.02-.67,2.52-1.12,4.07-1.12,3.76,0,4.68,2.7,4.68,5.26v4.84ZM11.66,16.53c-2.44-.05-5.21.4-5.21,2.91,0,1.55.97,2.24,2.08,2.24,1.63,0,2.67-1.07,3.02-2.16.08-.27.1-.53.1-.75v-2.24Z" />
|
||||
<path class="cls-1"
|
||||
d="M17.11,5h2.44v7.28h-.75c.87-1.44,2.44-2.35,4.62-2.35,3.39,0,5.75,2.67,5.75,6.57,0,4.62-3.08,6.92-6.11,6.92-1.96,0-2.72-.72-3.76-2.4h-.3l.1,2.11h-2.1c.06-.88.11-2.19.11-3.34V5ZM19.38,17.94c0,.29.08.59.17.85.45,1.63,1.21,2.75,3,2.75,2.61,0,4.12-2,4.12-4.97,0-2.59-1.4-4.81-4.06-4.81-1.65,0-2.55,1.12-3.06,2.89-.08.29-.17.61-.17.99v2.3Z" />
|
||||
<rect class="cls-1" x="1" y="23" width="2" height="4" />
|
||||
<rect class="cls-1" x="29" y="23" width="2" height="4" />
|
||||
<rect class="cls-1" x="1.67" y="25" width="29.33" height="2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-1"
|
||||
d="M10.41,14.93c0,.82.04,1.61.13,2.25h-1.47l-.13-1.18h-.06c-.5.74-1.47,1.4-2.76,1.4-1.83,0-2.76-1.34-2.76-2.7,0-2.27,1.94-3.52,5.43-3.5v-.19c0-.76-.2-2.18-2.05-2.16-.86,0-1.73.25-2.37.7l-.37-1.15c.75-.49,1.85-.82,2.98-.82,2.76,0,3.43,1.96,3.43,3.83v3.52ZM8.82,12.38c-1.79-.04-3.82.29-3.82,2.12,0,1.13.71,1.63,1.53,1.63,1.19,0,1.96-.78,2.22-1.57.06-.19.07-.39.07-.54v-1.63Z" />
|
||||
<path class="cls-1"
|
||||
d="M12.82,4h1.79v5.29h-.55c.64-1.05,1.79-1.71,3.39-1.71,2.49,0,4.21,1.94,4.21,4.78,0,3.36-2.26,5.03-4.48,5.03-1.44,0-2-.52-2.76-1.75h-.22l.08,1.54h-1.54c.04-.64.08-1.59.08-2.43V4ZM14.49,13.41c0,.21.06.43.12.62.33,1.19.89,2,2.2,2,1.91,0,3.02-1.46,3.02-3.61,0-1.88-1.03-3.5-2.98-3.5-1.21,0-1.87.82-2.24,2.1-.06.21-.12.45-.12.72v1.67Z" />
|
||||
<rect class="cls-1" x="1" y="17" width="1.47" height="3" />
|
||||
<rect class="cls-1" x="21.54" y="17" width="1.47" height="3" />
|
||||
<rect class="cls-1" x="1.49" y="18.55" width="21.52" height="1.45" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g>
|
||||
<path class="cls-1"
|
||||
d="M6.9,10.2c0,.61.03,1.21.1,1.69h-1.15l-.1-.89h-.04c-.39.55-1.15,1.05-2.16,1.05-1.43,0-2.16-1.01-2.16-2.03,0-1.71,1.52-2.64,4.24-2.62v-.15c0-.57-.16-1.63-1.6-1.62-.67,0-1.35.19-1.85.52l-.29-.86c.58-.36,1.44-.61,2.33-.61,2.16,0,2.68,1.47,2.68,2.87v2.64ZM5.66,8.29c-1.4-.03-2.99.22-2.99,1.59,0,.85.55,1.22,1.19,1.22.93,0,1.53-.58,1.73-1.18.04-.15.06-.29.06-.41v-1.22Z" />
|
||||
<path class="cls-1"
|
||||
d="M8.73,2h1.27v3.97h-.39c.45-.79,1.27-1.28,2.4-1.28,1.76,0,2.99,1.46,2.99,3.58,0,2.52-1.6,3.77-3.18,3.77-1.02,0-1.42-.39-1.95-1.31h.13l-.23,1.15h-1.09c.03-.48.06-1.19.06-1.82V2ZM9.93,9.06c0,.16.01.32.06.47.23.89.64,1.5,1.58,1.5,1.35,0,2.14-1.09,2.14-2.71,0-1.41-.73-2.62-2.11-2.62-.86,0-1.33.61-1.59,1.57-.04.16-.07.33-.07.54v1.25Z" />
|
||||
</g>
|
||||
<rect class="cls-1" y="12" width="1" height="2" />
|
||||
<rect class="cls-1" x="15" y="12.02" width="1" height="1.98" />
|
||||
<rect class="cls-1" y="13" width="16" height="1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="cls-1" x="20.04" y="2" width="2" height="22" />
|
||||
<rect class="cls-1" x="20.04" y="2" width="2" height="22"
|
||||
transform="translate(-.9 24.42) rotate(-59.21)" />
|
||||
<rect class="cls-1" x="10.04" y="12" width="22" height="2"
|
||||
transform="translate(-3.69 13.25) rotate(-32.29)" />
|
||||
<rect class="cls-1" x="2.04" y="22" width="8" height="8" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 590 B |
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="cls-1" x="14.46" y="2" width="1.38" height="15.14" />
|
||||
<rect class="cls-1" x="14.46" y="2" width="1.38" height="15.14"
|
||||
transform="translate(-.83 17.68) rotate(-59.21)" />
|
||||
<rect class="cls-1" x="7.58" y="8.88" width="15.14" height="1.38"
|
||||
transform="translate(-2.77 9.57) rotate(-32.29)" />
|
||||
<rect class="cls-1" x="2.08" y="16.5" width="5.5" height="5.5" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 615 B |
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="cls-1" x="10" y="1" width="1" height="11" />
|
||||
<rect class="cls-1" x="10" y="1" width="1" height="11"
|
||||
transform="translate(-.46 12.19) rotate(-59.21)" />
|
||||
<rect class="cls-1" x="5" y="6" width="11" height="1"
|
||||
transform="translate(-1.85 6.61) rotate(-32.29)" />
|
||||
<rect class="cls-1" x="1" y="11" width="4" height="4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 576 B |
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-1"
|
||||
d="M13,24.99c0,.67-.03,1.49.05,2.01h-1.25l-.11-1.14h-.05c-.43.6-1.25,1.14-2.34,1.14-1.55,0-2.34-1.09-2.34-2.2,0-1.85,1.65-2.87,4.61-2.85v-.16c0-.62-.17-1.33-1.74-1.31-.73,0-1.47.3-2.01.66l-.79-1.19c.63-.4,2.05-.95,3.01-.95,2.34,0,2.98,1.6,2.98,3.12v2.87ZM11.59,23.14c-1.21-.03-3.03.19-3.03,1.38,0,.73.39,1.06,1.48,1.06.81,0,1.33-.51,1.51-1.02.04-.13.05-.25.05-.35v-1.06Z" />
|
||||
<path class="cls-1"
|
||||
d="M22.05,8.99c0,.67-.03,1.49.05,2.01h-1.25l-.11-1.14h-.05c-.43.6-1.25,1.14-2.34,1.14-1.55,0-2.34-1.09-2.34-2.2,0-1.85,1.65-2.87,4.61-2.85v-.16c0-.62-.17-1.33-1.74-1.31-.73,0-1.47.3-2.01.66l-.79-1.19c.63-.4,2.05-.95,3.01-.95,2.34,0,2.98,1.6,2.98,3.12v2.87ZM20.64,7.14c-1.21-.03-3.03.19-3.03,1.38,0,.73.39,1.06,1.48,1.06.81,0,1.33-.51,1.51-1.02.04-.13.05-.25.05-.35v-1.06Z" />
|
||||
<path class="cls-1"
|
||||
d="M23.06,1.07h1.83v4.33h.03c.43-.77,1.2-1.25,2.27-1.25,1.66,0,2.82,1.42,2.82,3.5,0,2.46-1.51,3.69-3,3.69-.96,0-1.73-.38-2.24-1.28h-.03l-.07,1.12h-1.66c.03-.47.06-1.17.06-1.78V1.07ZM24.85,8.26c0,.12.01.24.05.35.2.67.84,1.13,1.62,1.13,1.14,0,1.8-.82,1.8-2.03,0-1.06-.61-1.97-1.78-1.97-.72,0-1.41.46-1.63,1.18-.04.12-.06.25-.06.4v.94Z" />
|
||||
<path class="cls-1"
|
||||
d="M20.97,26.56c-.36.17-1.16.44-2.19.44-2.3,0-3.79-1.56-3.79-3.88s1.6-4.06,4.09-4.06c.82,0,1.54.2,1.92.41v1.65c-.34-.17-1.16-.46-1.92-.46-1.19,0-2.09.77-2.09,2.34,0,1.76,1.03,2.29,2.04,2.29.79,0,1.54-.16,1.94-.33v1.6Z" />
|
||||
<path class="cls-1" d="M24,18v10H4v-10h20M26,16H2v14h24v-14h0Z" />
|
||||
<polygon class="cls-1" points="9 12 9 14 28 14 28 28 30 28 30 12 9 12" />
|
||||
<g>
|
||||
<path class="cls-1"
|
||||
d="M6,13h-2v-2.98c0-2.77,2.25-5.02,5.02-5.02h4.98v2h-4.98c-1.67,0-3.02,1.36-3.02,3.02v2.98Z" />
|
||||
<polygon class="cls-1" points="5 15 2 11 8 11 5 15" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-1"
|
||||
d="M9.25,19.01c0,.5-.02,1.12.04,1.51h-.94l-.08-.86h-.04c-.32.45-.94.86-1.76.86-1.16,0-1.76-.82-1.76-1.65,0-1.39,1.24-2.15,3.46-2.14v-.12c0-.46-.13-1-1.31-.98-.55,0-1.1.22-1.51.5l-.6-.89c.48-.3,1.53-.71,2.26-.71,1.76,0,2.23,1.2,2.23,2.34v2.15ZM8.19,17.63c-.91-.02-2.28.14-2.28,1.03,0,.55.29.8,1.11.8.61,0,1-.38,1.13-.77.03-.09.04-.19.04-.27v-.8Z" />
|
||||
<path class="cls-1"
|
||||
d="M16.04,7.01c0,.5-.02,1.12.04,1.51h-.94l-.08-.86h-.04c-.32.45-.94.86-1.76.86-1.16,0-1.76-.82-1.76-1.65,0-1.39,1.24-2.15,3.46-2.14v-.12c0-.46-.13-1-1.31-.98-.55,0-1.1.22-1.51.5l-.6-.89c.48-.3,1.53-.71,2.26-.71,1.76,0,2.23,1.2,2.23,2.34v2.15ZM14.98,5.63c-.91-.02-2.28.14-2.28,1.03,0,.55.29.8,1.11.8.61,0,1-.38,1.13-.77.03-.09.04-.19.04-.27v-.8Z" />
|
||||
<path class="cls-1"
|
||||
d="M16.79,1.07h1.37v3.24h.02c.32-.58.9-.94,1.7-.94,1.25,0,2.12,1.07,2.12,2.63,0,1.85-1.13,2.76-2.25,2.76-.72,0-1.3-.29-1.68-.96h-.02l-.05.84h-1.25c.02-.35.04-.88.04-1.33V1.07ZM18.14,6.46c0,.09,0,.18.04.26.15.5.63.84,1.22.84.86,0,1.35-.61,1.35-1.53,0-.8-.46-1.48-1.34-1.48-.54,0-1.06.34-1.22.89-.03.09-.05.19-.05.3v.7Z" />
|
||||
<path class="cls-1"
|
||||
d="M15.23,20.19c-.27.13-.87.33-1.64.33-1.72,0-2.84-1.17-2.84-2.91s1.2-3.04,3.07-3.04c.61,0,1.16.15,1.44.31v1.23c-.25-.13-.87-.34-1.44-.34-.89,0-1.57.58-1.57,1.76,0,1.32.77,1.72,1.53,1.72.59,0,1.16-.12,1.45-.25v1.2Z" />
|
||||
<path class="cls-1" d="M17.5,13.77v7.5H2.5v-7.5h15M19,12.27H1v10.5h18v-10.5h0Z" />
|
||||
<polygon class="cls-1"
|
||||
points="6.25 9.27 6.25 10.77 20.5 10.77 20.5 21.27 22 21.27 22 9.27 6.25 9.27" />
|
||||
<g>
|
||||
<path class="cls-1"
|
||||
d="M4,10.02h-1.5v-2.23c0-2.08,1.69-3.77,3.77-3.77h3.73v1.5h-3.73c-1.25,0-2.27,1.02-2.27,2.27v2.23Z" />
|
||||
<polygon class="cls-1" points="3.25 11.52 1 8.52 5.5 8.52 3.25 11.52" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-1"
|
||||
d="M6.5,13.49c0,.33-.01.74.02,1.01h-.63l-.06-.57h-.02c-.21.3-.63.57-1.17.57-.78,0-1.17-.55-1.17-1.1,0-.93.82-1.43,2.3-1.43v-.08c0-.31-.09-.66-.87-.66-.36,0-.74.15-1.01.33l-.4-.59c.32-.2,1.02-.48,1.51-.48,1.17,0,1.49.8,1.49,1.56v1.43ZM5.8,12.57c-.61-.01-1.52.09-1.52.69,0,.37.19.53.74.53.4,0,.66-.25.75-.51.02-.06.03-.13.03-.18v-.53Z" />
|
||||
<path class="cls-1"
|
||||
d="M11.02,4.49c0,.33-.01.74.02,1.01h-.63l-.06-.57h-.02c-.21.3-.63.57-1.17.57-.78,0-1.17-.55-1.17-1.1,0-.93.82-1.43,2.3-1.43v-.08c0-.31-.09-.66-.87-.66-.36,0-.74.15-1.01.33l-.4-.59c.32-.2,1.02-.48,1.51-.48,1.17,0,1.49.8,1.49,1.56v1.43ZM10.32,3.57c-.61-.01-1.52.09-1.52.69,0,.37.19.53.74.53.4,0,.66-.25.75-.51.02-.06.03-.13.03-.18v-.53Z" />
|
||||
<path class="cls-1"
|
||||
d="M11.53.54h.91v2.16h.01c.21-.38.6-.63,1.13-.63.83,0,1.41.71,1.41,1.75,0,1.23-.76,1.84-1.5,1.84-.48,0-.87-.19-1.12-.64h-.01l-.03.56h-.83c.01-.23.03-.58.03-.89V.54ZM12.43,4.13c0,.06,0,.12.02.17.1.33.42.56.81.56.57,0,.9-.41.9-1.02,0-.53-.31-.98-.89-.98-.36,0-.71.23-.82.59-.02.06-.03.13-.03.2v.47Z" />
|
||||
<path class="cls-1"
|
||||
d="M10.48,14.28c-.18.09-.58.22-1.09.22-1.15,0-1.89-.78-1.89-1.94s.8-2.03,2.04-2.03c.41,0,.77.1.96.2v.82c-.17-.09-.58-.23-.96-.23-.59,0-1.04.38-1.04,1.17,0,.88.51,1.15,1.02,1.15.39,0,.77-.08.97-.17v.8Z" />
|
||||
<path class="cls-1" d="M12,10v5H2v-5h10M13,9H1v7h12v-7h0Z" />
|
||||
<polygon class="cls-1" points="4.5 7 4.5 8 14 8 14 15 15 15 15 7 4.5 7" />
|
||||
<g>
|
||||
<path class="cls-1"
|
||||
d="M3,7h-1v-1.49c0-1.38,1.13-2.51,2.51-2.51h2.49v1h-2.49c-.83,0-1.51.68-1.51,1.51v1.49Z" />
|
||||
<polygon class="cls-1" points="2.5 8 1 6 4 6 2.5 8" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-1"
|
||||
d="M20.06,2h2.09v4.78h.03c.49-.85,1.37-1.38,2.59-1.38,1.9,0,3.22,1.57,3.22,3.87,0,2.72-1.73,4.07-3.43,4.07-1.1,0-1.98-.42-2.56-1.41h-.03l-.08,1.24h-1.9c.03-.52.06-1.29.06-1.96V2ZM22.11,9.94c0,.13.01.27.06.39.22.74.95,1.24,1.85,1.24,1.3,0,2.06-.91,2.06-2.25,0-1.17-.7-2.17-2.03-2.17-.83,0-1.61.51-1.87,1.3-.04.13-.07.28-.07.45v1.04Z" />
|
||||
<path class="cls-1"
|
||||
d="M17.97,25.56c-.36.17-1.16.44-2.19.44-2.3,0-3.79-1.56-3.79-3.88s1.6-4.06,4.09-4.06c.82,0,1.54.2,1.92.41v1.65c-.34-.17-1.16-.46-1.92-.46-1.19,0-2.09.81-2.09,2.38,0,1.76,1.03,2.25,2.04,2.25.79,0,1.54-.16,1.94-.33v1.6Z" />
|
||||
<path class="cls-1" d="M26,16v12H6v-12h20M28,14H4v16h24V14h0Z" />
|
||||
<path class="cls-1"
|
||||
d="M10,10h-2v-2.98c0-2.77,2.25-5.02,5.02-5.02h4.98v2h-4.98c-1.67,0-3.02,1.36-3.02,3.02v2.98Z" />
|
||||
<polygon class="cls-1" points="9 12 6 8 12 8 9 12" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-1"
|
||||
d="M15.62.88h1.64v3.75h.02c.38-.67,1.07-1.09,2.04-1.09,1.49,0,2.53,1.24,2.53,3.04,0,2.14-1.36,3.2-2.69,3.2-.86,0-1.56-.33-2.01-1.11h-.02l-.06.98h-1.49c.02-.41.05-1.01.05-1.54V.88ZM17.23,7.12c0,.1.01.21.04.3.18.58.75.98,1.46.98,1.03,0,1.62-.71,1.62-1.77,0-.92-.55-1.71-1.6-1.71-.65,0-1.27.4-1.47,1.03-.03.1-.06.22-.06.35v.82Z" />
|
||||
<path class="cls-1"
|
||||
d="M13.98,19.4c-.28.14-.91.35-1.72.35-1.8,0-2.98-1.22-2.98-3.05s1.26-3.19,3.21-3.19c.64,0,1.21.16,1.51.32v1.29c-.27-.14-.91-.36-1.51-.36-.93,0-1.64.64-1.64,1.87,0,1.38.81,1.77,1.6,1.77.62,0,1.21-.13,1.52-.26v1.26Z" />
|
||||
<path class="cls-1" d="M20.29,11.88v9.43H4.57v-9.43h15.71M21.86,10.31H3v12.57h18.86v-12.57h0Z" />
|
||||
<path class="cls-1"
|
||||
d="M7.71,7.17h-1.57v-2.34c0-2.18,1.77-3.95,3.95-3.95h3.91v1.57h-3.91c-1.31,0-2.37,1.07-2.37,2.37v2.34Z" />
|
||||
<polygon class="cls-1" points="6.93 8.74 4.57 5.6 9.29 5.6 6.93 8.74" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-1"
|
||||
d="M10.03,1h1.04v2.39h.02c.24-.42.68-.69,1.3-.69.95,0,1.61.79,1.61,1.93,0,1.36-.86,2.04-1.71,2.04-.55,0-.99-.21-1.28-.71h-.02l-.04.62h-.95c.02-.26.03-.64.03-.98V1ZM11.06,4.97c0,.07,0,.13.03.19.11.37.48.62.93.62.65,0,1.03-.45,1.03-1.12,0-.59-.35-1.09-1.02-1.09-.41,0-.81.25-.93.65-.02.07-.04.14-.04.22v.52Z" />
|
||||
<path class="cls-1"
|
||||
d="M8.99,13.78c-.18.09-.58.22-1.09.22-1.15,0-1.89-.78-1.89-1.94s.8-2.03,2.04-2.03c.41,0,.77.1.96.2v.82c-.17-.09-.58-.23-.96-.23-.59,0-1.04.4-1.04,1.19,0,.88.51,1.13,1.02,1.13.39,0,.77-.08.97-.17v.8Z" />
|
||||
<path class="cls-1" d="M13,9v6H3v-6h10M14,8H2v8h12V8h0Z" />
|
||||
<path class="cls-1"
|
||||
d="M5,5h-1v-1.49c0-1.38,1.13-2.51,2.51-2.51h2.49v1h-2.49c-.83,0-1.51.68-1.51,1.51v1.49Z" />
|
||||
<polygon class="cls-1" points="4.5 6 3 4 6 4 4.5 6" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -7,26 +7,28 @@
|
||||
"exports": {
|
||||
".": "./lib/index.js",
|
||||
"./*.css": "./src/*.css",
|
||||
"./*": "./lib/*.js"
|
||||
"./*": "./lib/*.js",
|
||||
"./assets/icons/*.svg": "./assets/icons/*.svg"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc -b",
|
||||
"docs": "ladle serve",
|
||||
"clean": "rimraf --glob lib"
|
||||
},
|
||||
"packageManager": "yarn@4.6.0",
|
||||
"packageManager": "yarn@4.9.2",
|
||||
"devDependencies": {
|
||||
"@dbeaver/tsconfig": "workspace:^",
|
||||
"@ladle/react": "^5",
|
||||
"@tailwindcss/vite": "^4",
|
||||
"@tailwindcss/vite": "4.0.7",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"@wroud/vite-plugin-asset-resolver": "^0",
|
||||
"@wroud/vite-plugin-tsc": "^0.11.6",
|
||||
"rimraf": "^6",
|
||||
"tailwindcss": "^4",
|
||||
"tailwindcss": "4.0.7",
|
||||
"typescript": "^5",
|
||||
"vite": "^6"
|
||||
"vite": "^7",
|
||||
"vite-plugin-svgr": "^4.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ariakit/react": "^0",
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
export default function template(files) {
|
||||
const exportLines = files.map((file) => {
|
||||
const { path } = file;
|
||||
|
||||
const fileName = path.split('/').pop();
|
||||
const componentNameWithExt = fileName.replace(/\.tsx$/, '.js');
|
||||
const componentName = fileName.replace(/\.tsx$/, '');
|
||||
|
||||
return `export { default as ${componentName} } from './${componentNameWithExt}';`;
|
||||
});
|
||||
|
||||
|
||||
const header = '/* This file is automatically generated by the build:icons script. Do not modify it manually.*/\n\n ';
|
||||
|
||||
return header + exportLines.join('\n');
|
||||
};
|
||||
@@ -4,19 +4,8 @@
|
||||
|
||||
@layer base {
|
||||
.dbv-kit-button {
|
||||
display: inline-flex;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
|
||||
height: var(--dbv-kit-btn-height);
|
||||
padding-inline: var(--dbv-kit-btn-padding-inline);
|
||||
gap: var(--dbv-kit-btn-gap);
|
||||
|
||||
background-color: var(--dbv-kit-btn-background);
|
||||
color: var(--dbv-kit-btn-foreground);
|
||||
@@ -29,6 +18,8 @@
|
||||
font-size: var(--dbv-kit-btn-font-size);
|
||||
font-weight: var(--dbv-kit-btn-font-weight);
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
&:focus-visible,
|
||||
&[data-focus-visible] {
|
||||
outline: var(--dbv-kit-control-outline-width) solid var(--dbv-kit-btn-outline-color);
|
||||
@@ -37,18 +28,16 @@
|
||||
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
color: var(--dbv-kit-btn-foreground-hover);
|
||||
background-color: var(--dbv-kit-btn-background-hover);
|
||||
}
|
||||
}
|
||||
|
||||
&:active,
|
||||
&[data-active] {
|
||||
color: var(--dbv-kit-btn-foreground-active);
|
||||
background-color: var(--dbv-kit-btn-background-active);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: var(--dbv-kit-control-disabled-opacity);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------- */
|
||||
@@ -94,72 +83,76 @@
|
||||
/* Variants */
|
||||
|
||||
.dbv-kit-button--primary {
|
||||
--dbv-kit-btn-background: var(--dbv-kit-btn-primary-background);
|
||||
--dbv-kit-btn-foreground: var(--dbv-kit-btn-primary-foreground);
|
||||
--dbv-kit-btn-foreground-hover: var(--dbv-kit-btn-primary-foreground-hover);
|
||||
--dbv-kit-btn-foreground-active: var(--dbv-kit-btn-primary-foreground-active);
|
||||
|
||||
--dbv-kit-btn-background: var(--dbv-kit-btn-primary-background);
|
||||
--dbv-kit-btn-background-hover: var(--dbv-kit-btn-primary-background-hover);
|
||||
--dbv-kit-btn-background-active: var(--dbv-kit-btn-primary-background-active);
|
||||
|
||||
--dbv-kit-btn-loader-color: var(--dbv-kit-btn-background-hover);
|
||||
--dbv-kit-btn-loader-background: var(--dbv-kit-btn-loader-base-color);
|
||||
--dbv-kit-btn-loader-color: var(--dbv-kit-btn-primary-foreground);
|
||||
|
||||
&:disabled {
|
||||
background-color: var(--dbv-kit-control-disabled-background);
|
||||
color: var(--dbv-kit-control-disabled-foreground);
|
||||
}
|
||||
}
|
||||
|
||||
.dbv-kit-button--secondary {
|
||||
--dbv-kit-btn-background: var(--dbv-kit-btn-secondary-background);
|
||||
--dbv-kit-btn-foreground: var(--dbv-kit-btn-secondary-foreground);
|
||||
--dbv-kit-btn-foreground-hover: var(--dbv-kit-btn-secondary-foreground-hover);
|
||||
--dbv-kit-btn-foreground-active: var(--dbv-kit-btn-secondary-foreground-active);
|
||||
|
||||
--dbv-kit-btn-background: var(--dbv-kit-btn-secondary-background);
|
||||
--dbv-kit-btn-background-hover: var(--dbv-kit-btn-secondary-background-hover);
|
||||
--dbv-kit-btn-background-active: var(--dbv-kit-btn-secondary-background-active);
|
||||
--dbv-kit-btn-border-color: var(--dbv-kit-btn-secondary-border-color);
|
||||
|
||||
--dbv-kit-btn-loader-color: var(--dbv-kit-btn-secondary-foreground);
|
||||
--dbv-kit-btn-loader-background: var(--dbv-kit-btn-secondary-background-active);
|
||||
|
||||
&:disabled {
|
||||
color: var(--dbv-kit-control-disabled-foreground);
|
||||
border-color: var(--dbv-kit-control-disabled-foreground);
|
||||
}
|
||||
}
|
||||
|
||||
.dbv-kit-button--danger {
|
||||
--dbv-kit-btn-background: var(--dbv-kit-btn-danger-background);
|
||||
--dbv-kit-btn-foreground: var(--dbv-kit-btn-danger-foreground);
|
||||
--dbv-kit-btn-foreground-hover: var(--dbv-kit-btn-danger-foreground);
|
||||
--dbv-kit-btn-foreground-active: var(--dbv-kit-btn-danger-foreground-active);
|
||||
|
||||
--dbv-kit-btn-background: var(--dbv-kit-btn-danger-background);
|
||||
--dbv-kit-btn-background-hover: var(--dbv-kit-btn-danger-background-hover);
|
||||
--dbv-kit-btn-background-active: var(--dbv-kit-btn-danger-background-active);
|
||||
--dbv-kit-btn-border-color: var(--dbv-kit-btn-danger-border-color);
|
||||
|
||||
--dbv-kit-btn-loader-color: var(--dbv-kit-btn-danger-background);
|
||||
--dbv-kit-btn-loader-background: var(--dbv-kit-btn-loader-base-color);
|
||||
--dbv-kit-btn-loader-color: var(--dbv-kit-btn-danger-foreground);
|
||||
--dbv-kit-btn-outline-color: var(--dbv-kit-btn-danger-color-outline);
|
||||
|
||||
&:disabled {
|
||||
background-color: var(--dbv-kit-control-disabled-background);
|
||||
color: var(--dbv-kit-control-disabled-foreground);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------- */
|
||||
/* Loader */
|
||||
|
||||
.dbv-kit-button[data-loading='true'] {
|
||||
opacity: 0.75;
|
||||
color: color-mix(in oklch, var(--dbv-kit-btn-foreground) 25%, var(--dbv-kit-btn-loader-base-color));
|
||||
background-color: color-mix(in oklch, var(--dbv-kit-btn-loader-base-color) 75%, var(--dbv-kit-btn-background));
|
||||
background-color: var(--dbv-kit-btn-background-hover);
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&[data-active] {
|
||||
background-color: color-mix(in oklch, var(--dbv-kit-btn-loader-base-color) 85%, var(--dbv-kit-btn-background));
|
||||
background-color: var(--dbv-kit-btn-background-active);
|
||||
}
|
||||
}
|
||||
|
||||
.dbv-kit-button__loader {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
pointer-events: none;
|
||||
|
||||
&::after {
|
||||
--loader-width: calc(var(--dbv-kit-btn-font-size) * 0.2);
|
||||
content: '';
|
||||
border: var(--loader-width) solid var(--dbv-kit-btn-loader-background);
|
||||
border-top: var(--loader-width) solid var(--dbv-kit-btn-loader-color);
|
||||
border-radius: 50%;
|
||||
opacity: 1;
|
||||
width: calc(var(--dbv-kit-btn-font-size) * 1.25);
|
||||
height: calc(var(--dbv-kit-btn-font-size) * 1.25);
|
||||
animation: var(--dbv-kit-btn-loader-animation);
|
||||
}
|
||||
.dbv-kit-button .dbv-kit-spinner {
|
||||
--dbv-kit-spinner-stroke-color: var(--dbv-kit-btn-loader-color);
|
||||
--dbv-kit-spinner-height: calc(var(--dbv-kit-btn-height) * 0.6);
|
||||
--dbv-kit-spinner-stroke-width: 3px;
|
||||
}
|
||||
|
||||
/* ---------------------------- */
|
||||
|
||||
@@ -5,33 +5,21 @@
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { Button as AriaButton, type ButtonProps as AriaKitButtonProps } from '@ariakit/react';
|
||||
import clsx from 'clsx';
|
||||
import './Button.css';
|
||||
import type { ControlSize } from '../types/controls.js';
|
||||
import { componentProviderWrapper } from '../componentProviderWrapper.js';
|
||||
import { ButtonRoot, type ButtonRootProps } from './ButtonRoot.js';
|
||||
import './Button.css';
|
||||
|
||||
export interface ButtonProps extends Omit<AriaKitButtonProps, 'clickOnEnter' | 'clickOnSpace'> {
|
||||
export interface ButtonProps extends ButtonRootProps {
|
||||
variant?: 'primary' | 'secondary' | 'danger';
|
||||
size?: ControlSize;
|
||||
loading?: boolean;
|
||||
loader?: React.ReactNode;
|
||||
}
|
||||
|
||||
export function ButtonBase({ className, variant = 'primary', size = 'medium', loading, loader, children, onClick, ...props }: ButtonProps) {
|
||||
export function ButtonBase({ className, variant = 'primary', size = 'medium', ...props }: ButtonProps) {
|
||||
const classToApply = clsx('dbv-kit-button', `dbv-kit-button--${variant}`, `dbv-kit-button--${size}`, className);
|
||||
|
||||
if (loading) {
|
||||
props['aria-busy'] = true;
|
||||
props['data-loading'] = true;
|
||||
}
|
||||
|
||||
return (
|
||||
<AriaButton onClick={loading ? () => null : onClick} className={classToApply} {...props}>
|
||||
{loading && (loader ? loader : <span className="dbv-kit-button__loader" />)}
|
||||
{children}
|
||||
</AriaButton>
|
||||
);
|
||||
return <ButtonRoot className={classToApply} {...props} />;
|
||||
}
|
||||
export interface ButtonIconProps extends React.HTMLAttributes<HTMLSpanElement> {
|
||||
placement?: 'start' | 'end';
|
||||
@@ -42,9 +30,10 @@ export interface ButtonIconProps extends React.HTMLAttributes<HTMLSpanElement> {
|
||||
*
|
||||
* @param props.placement This property is needed to adjust icon placement inside a button. The icon with placement="start" will cut the inline-start padding. placement="end" will affect the padding-inline-end accordingly. This property supports RTL and LTR, so you don't need to think about it.
|
||||
*/
|
||||
ButtonBase.Icon = function ButtonBaseIcon({ className, children, placement }: ButtonIconProps) {
|
||||
export function ButtonBaseIcon({ className, children, placement }: ButtonIconProps) {
|
||||
const classToApply = clsx('dbv-kit-button__icon', placement && `dbv-kit-button__icon--${placement}`, className);
|
||||
return <span className={classToApply}>{children}</span>;
|
||||
};
|
||||
}
|
||||
|
||||
export const Button = componentProviderWrapper('Button', ButtonBase);
|
||||
export const ButtonIcon = componentProviderWrapper('ButtonIcon', ButtonBaseIcon);
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
@layer base {
|
||||
.dbv-kit-button__loader {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.dbv-kit-button__content {
|
||||
display: flex;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
user-select: none;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
gap: var(--dbv-kit-btn-gap);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Button as AriaButton, type ButtonProps as AriaKitButtonProps } from '@ariakit/react';
|
||||
import { Spinner } from '../Spinner/Spinner.js';
|
||||
import { clsx } from '../utils/clsx.js';
|
||||
import './ButtonRoot.css';
|
||||
|
||||
export interface ButtonRootProps extends Omit<AriaKitButtonProps, 'clickOnEnter' | 'clickOnSpace'> {
|
||||
loading?: boolean;
|
||||
loader?: React.ReactNode;
|
||||
}
|
||||
|
||||
export function ButtonRoot({ loading, loader, children, onClick, className, ...props }: ButtonRootProps) {
|
||||
if (loading) {
|
||||
props['aria-busy'] = true;
|
||||
props['data-loading'] = true;
|
||||
}
|
||||
|
||||
return (
|
||||
<AriaButton onClick={loading ? () => null : onClick} className={clsx(className, 'tw:relative')} {...props}>
|
||||
<div className={clsx('dbv-kit-button__content', loading && 'tw:opacity-0')}>{children}</div>
|
||||
{loading && <div className="dbv-kit-button__loader">{loader ? loader : <Spinner />}</div>}
|
||||
</AriaButton>
|
||||
);
|
||||
}
|
||||
@@ -2,14 +2,18 @@
|
||||
:root {
|
||||
--dbv-kit-btn-height: var(--dbv-kit-control-height-medium);
|
||||
--dbv-kit-btn-padding-inline: calc(var(--tw-spacing) * 2.5);
|
||||
--dbv-kit-btn-gap: calc(var(--dbv-kit-btn-padding-inline) / 4);
|
||||
--dbv-kit-btn-gap: calc(var(--dbv-kit-btn-padding-inline) / 2);
|
||||
|
||||
--dbv-kit-btn-outline-offset: var(--dbv-kit-control-outline-offset);
|
||||
--dbv-kit-btn-outline-color: var(--dbv-kit-control-outline-color);
|
||||
|
||||
--dbv-kit-btn-foreground: var(--tw-color-white);
|
||||
--dbv-kit-btn-foreground-hover: var(--tw-color-white);
|
||||
--dbv-kit-btn-foreground-active: var(--tw-color-white);
|
||||
|
||||
--dbv-kit-btn-background: var(--dbv-kit-color-primary-600);
|
||||
--dbv-kit-btn-background-hover: var(--dbv-kit-color-primary-700);
|
||||
--dbv-kit-btn-background-active: var(--dbv-kit-color-primary-800);
|
||||
--dbv-kit-btn-outline-color: var(--dbv-kit-control-outline-color);
|
||||
|
||||
--dbv-kit-btn-border-width: var(--dbv-kit-control-border-width);
|
||||
--dbv-kit-btn-border-color: transparent;
|
||||
@@ -19,7 +23,7 @@
|
||||
--dbv-kit-btn-font-weight: var(--tw-font-weight-normal);
|
||||
--dbv-kit-btn-font-size: calc(var(--dbv-kit-font-size-base) * 0.875);
|
||||
|
||||
--dbv-kit-btn-loader-base-color: var(--tw-color-white);
|
||||
--dbv-kit-btn-loader-animation: var(--tw-animate-spin);
|
||||
--dbv-kit-btn-loader-base-color: var(--dbv-kit-btn-foreground);
|
||||
--dbv-kit-btn-loader-height: calc(var(--dbv-kit-btn-height) * 0.6);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,22 +2,30 @@
|
||||
:root {
|
||||
/* Primary Button */
|
||||
--dbv-kit-btn-primary-foreground: var(--tw-color-white);
|
||||
--dbv-kit-btn-primary-foreground-hover: var(--tw-color-white);
|
||||
--dbv-kit-btn-primary-foreground-active: var(--tw-color-white);
|
||||
--dbv-kit-btn-primary-background: var(--dbv-kit-color-primary-600);
|
||||
--dbv-kit-btn-primary-background-hover: var(--dbv-kit-color-primary-700);
|
||||
--dbv-kit-btn-primary-background-active: var(--dbv-kit-color-primary-800);
|
||||
|
||||
/* Secondary Button */
|
||||
--dbv-kit-btn-secondary-foreground: var(--dbv-kit-color-primary-600);
|
||||
--dbv-kit-btn-secondary-foreground-hover: var(--dbv-kit-color-primary-600);
|
||||
--dbv-kit-btn-secondary-foreground-active: var(--dbv-kit-color-primary-600);
|
||||
--dbv-kit-btn-secondary-background: transparent;
|
||||
--dbv-kit-btn-secondary-background-hover: var(--dbv-kit-color-primary-50);
|
||||
--dbv-kit-btn-secondary-background-active: var(--dbv-kit-color-primary-100);
|
||||
--dbv-kit-btn-secondary-border-color: var(--dbv-kit-color-primary-600);
|
||||
--dbv-kit-btn-secondary-border-color-hover: var(--dbv-kit-color-primary-600);
|
||||
|
||||
/* Danger Button */
|
||||
--dbv-kit-btn-danger-foreground: var(--tw-color-white);
|
||||
--dbv-kit-btn-danger-foreground-hover: var(--tw-color-white);
|
||||
--dbv-kit-btn-danger-foreground-active: var(--tw-color-white);
|
||||
--dbv-kit-btn-danger-background: var(--tw-color-red-600);
|
||||
--dbv-kit-btn-danger-background-hover: var(--tw-color-red-700);
|
||||
--dbv-kit-btn-danger-background-active: var(--tw-color-red-800);
|
||||
--dbv-kit-btn-danger-border-color: transparent;
|
||||
--dbv-kit-btn-danger-color-outline: var(--tw-color-red-300);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@ export function CheckboxBase({ children, className, icon, indeterminate, indeter
|
||||
>
|
||||
{checked &&
|
||||
(icon ?? (
|
||||
<svg fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 16 16">
|
||||
<polyline points="3,7 7,11 13,4" />
|
||||
<svg stroke="currentColor" strokeWidth="2" viewBox="0 0 16 16">
|
||||
<polyline fill="none" points="3,7 7,11 13,4" />
|
||||
</svg>
|
||||
))}
|
||||
{indeterminate &&
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createContext } from 'react';
|
||||
import type { ButtonBase } from './Button/Button.js';
|
||||
import type { ButtonBase, ButtonBaseIcon } from './Button/Button.js';
|
||||
import type { IconButtonBase } from './IconButton/IconButton.js';
|
||||
import type { CheckboxBase } from './Checkbox/Checkbox.js';
|
||||
import type { Radio } from './Radio/Radio.js';
|
||||
import type { InputBase } from './Input/Input.js';
|
||||
@@ -9,6 +10,8 @@ import type { SelectField } from './Select/SelectField.js';
|
||||
|
||||
export interface IComponentProvider {
|
||||
Button?: typeof ButtonBase;
|
||||
ButtonIcon?: typeof ButtonBaseIcon;
|
||||
IconButton?: typeof IconButtonBase;
|
||||
Input?: typeof InputBase;
|
||||
Checkbox?: typeof CheckboxBase;
|
||||
Radio?: typeof Radio;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import clsx from 'clsx';
|
||||
|
||||
type IconNames =
|
||||
| 'replace'
|
||||
| 'replace-all'
|
||||
| 'match-word'
|
||||
| 'case'
|
||||
| 'regex'
|
||||
| 'sort-asc'
|
||||
| 'sort-desc'
|
||||
| 'cross'
|
||||
| 'sort-unknown'
|
||||
| 'arrow-up'
|
||||
| 'arrow-down';
|
||||
|
||||
export interface IconProps {
|
||||
name: IconNames;
|
||||
className?: string;
|
||||
size?: 'small' | 'medium' | 'large';
|
||||
color?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
export function Icon({ name, className, size = 'small', color, style }: IconProps) {
|
||||
const sizeAffix = size === 'small' ? '_sm' : size === 'large' ? '' : '_m';
|
||||
const w = size === 'small' ? 16 : size === 'large' ? 32 : 24;
|
||||
return (
|
||||
<svg width={w} height={w} viewBox={`0 0 ${w} ${w}`} className={clsx('dbv-kit-icon', className)} style={{ color, ...style }}>
|
||||
<use href={`#icon-${name}${sizeAffix}`} />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
@import './_base.css';
|
||||
@import './_sizes.css';
|
||||
@import './_variants.css';
|
||||
|
||||
@layer base {
|
||||
.dbv-kit-icon-button {
|
||||
min-width: var(--dbv-kit-icon-btn-size);
|
||||
width: var(--dbv-kit-icon-btn-size);
|
||||
height: var(--dbv-kit-icon-btn-size);
|
||||
font-size: calc(var(--dbv-kit-icon-btn-size) * 0.75);
|
||||
|
||||
border-radius: var(--dbv-kit-icon-btn-border-radius);
|
||||
border-color: var(--dbv-kit-icon-btn-border-color);
|
||||
border-width: var(--dbv-kit-icon-btn-border-width);
|
||||
border-style: var(--dbv-kit-icon-btn-border-style);
|
||||
|
||||
color: var(--dbv-kit-icon-btn-foreground);
|
||||
background-color: var(--dbv-kit-icon-btn-background);
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
&:focus-visible,
|
||||
&[data-focus-visible] {
|
||||
outline: var(--dbv-kit-icon-btn-outline-width) solid var(--dbv-kit-icon-btn-outline-color);
|
||||
outline-offset: var(--dbv-kit-icon-btn-outline-offset);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
color: var(--dbv-kit-icon-btn-foreground-hover);
|
||||
background-color: var(--dbv-kit-icon-btn-background-hover);
|
||||
}
|
||||
}
|
||||
|
||||
&:active,
|
||||
&[data-active] {
|
||||
color: var(--dbv-kit-icon-btn-foreground-active);
|
||||
background-color: var(--dbv-kit-icon-btn-background-active);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: var(--dbv-kit-control-disabled-opacity);
|
||||
}
|
||||
|
||||
&[data-loading='true'] {
|
||||
background-color: var(--dbv-kit-icon-btn-background);
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&[data-active] {
|
||||
background-color: var(--dbv-kit-icon-btn-background-active);
|
||||
}
|
||||
}
|
||||
|
||||
.dbv-kit-spinner {
|
||||
--dbv-kit-spinner-stroke-color: var(--dbv-kit-icon-btn-loader-color);
|
||||
--dbv-kit-spinner-height: calc(var(--dbv-kit-icon-btn-size) * 0.8);
|
||||
--dbv-kit-spinner-stroke-width: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Size variants */
|
||||
.dbv-kit-icon-button--small {
|
||||
--dbv-kit-icon-btn-size: var(--dbv-kit-icon-btn-small-size);
|
||||
}
|
||||
|
||||
.dbv-kit-icon-button--medium {
|
||||
--dbv-kit-icon-btn-size: var(--dbv-kit-icon-btn-medium-size);
|
||||
}
|
||||
|
||||
.dbv-kit-icon-button--large {
|
||||
--dbv-kit-icon-btn-size: var(--dbv-kit-icon-btn-large-size);
|
||||
}
|
||||
|
||||
.dbv-kit-icon-button--xlarge {
|
||||
--dbv-kit-icon-btn-size: var(--dbv-kit-icon-btn-xlarge-size);
|
||||
}
|
||||
|
||||
/* Variant styles */
|
||||
.dbv-kit-icon-button--primary {
|
||||
--dbv-kit-icon-btn-foreground: var(--dbv-kit-icon-btn-primary-foreground);
|
||||
--dbv-kit-icon-btn-foreground-hover: var(--dbv-kit-icon-btn-primary-foreground-hover);
|
||||
--dbv-kit-icon-btn-foreground-active: var(--dbv-kit-icon-btn-primary-foreground-active);
|
||||
--dbv-kit-icon-btn-background: var(--dbv-kit-icon-btn-primary-background);
|
||||
--dbv-kit-icon-btn-background-hover: var(--dbv-kit-icon-btn-primary-background-hover);
|
||||
--dbv-kit-icon-btn-background-active: var(--dbv-kit-icon-btn-primary-background-active);
|
||||
--dbv-kit-icon-btn-loader-color: var(--dbv-kit-icon-btn-primary-foreground);
|
||||
}
|
||||
|
||||
.dbv-kit-icon-button--secondary {
|
||||
--dbv-kit-icon-btn-foreground: var(--dbv-kit-icon-btn-secondary-foreground);
|
||||
--dbv-kit-icon-btn-foreground-hover: var(--dbv-kit-icon-btn-secondary-foreground-hover);
|
||||
--dbv-kit-icon-btn-foreground-active: var(--dbv-kit-icon-btn-secondary-foreground-active);
|
||||
--dbv-kit-icon-btn-background: var(--dbv-kit-icon-btn-secondary-background);
|
||||
--dbv-kit-icon-btn-background-hover: var(--dbv-kit-icon-btn-secondary-background-hover);
|
||||
--dbv-kit-icon-btn-background-active: var(--dbv-kit-icon-btn-secondary-background-active);
|
||||
--dbv-kit-icon-btn-border-color: var(--dbv-kit-icon-btn-secondary-border-color);
|
||||
--dbv-kit-icon-btn-loader-color: var(--dbv-kit-icon-btn-secondary-loader-color);
|
||||
}
|
||||
|
||||
.dbv-kit-icon-button--danger {
|
||||
--dbv-kit-icon-btn-foreground: var(--dbv-kit-icon-btn-danger-foreground);
|
||||
--dbv-kit-icon-btn-foreground-hover: var(--dbv-kit-icon-btn-danger-foreground-hover);
|
||||
--dbv-kit-icon-btn-foreground-active: var(--dbv-kit-icon-btn-danger-foreground-active);
|
||||
--dbv-kit-icon-btn-background: var(--dbv-kit-icon-btn-danger-background);
|
||||
--dbv-kit-icon-btn-background-hover: var(--dbv-kit-icon-btn-danger-background-hover);
|
||||
--dbv-kit-icon-btn-background-active: var(--dbv-kit-icon-btn-danger-background-active);
|
||||
--dbv-kit-icon-btn-loader-color: var(--dbv-kit-icon-btn-danger-loader-color);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { clsx } from 'clsx';
|
||||
|
||||
import { componentProviderWrapper } from '../componentProviderWrapper.js';
|
||||
import { ButtonRoot, type ButtonRootProps } from '../Button/ButtonRoot.js';
|
||||
import type { ControlSize } from '../types/controls.js';
|
||||
|
||||
import './IconButton.css';
|
||||
|
||||
export interface IconButtonProps extends ButtonRootProps {
|
||||
'aria-label': string;
|
||||
variant?: 'primary' | 'secondary' | 'danger';
|
||||
size?: ControlSize;
|
||||
}
|
||||
|
||||
export function IconButtonBase({ className, variant = 'primary', size = 'medium', children, ...props }: IconButtonProps) {
|
||||
const classToApply = clsx('dbv-kit-icon-button', `dbv-kit-icon-button--${variant}`, `dbv-kit-icon-button--${size}`, className);
|
||||
|
||||
return (
|
||||
<ButtonRoot className={classToApply} {...props}>
|
||||
{children}
|
||||
</ButtonRoot>
|
||||
);
|
||||
}
|
||||
|
||||
export const IconButton = componentProviderWrapper('IconButton', IconButtonBase);
|
||||
@@ -0,0 +1,30 @@
|
||||
@layer base {
|
||||
:root {
|
||||
/* Icon Button border variables */
|
||||
--dbv-kit-icon-btn-border-radius: var(--dbv-kit-btn-border-radius);
|
||||
--dbv-kit-icon-btn-border-width: var(--dbv-kit-btn-border-width);
|
||||
--dbv-kit-icon-btn-border-style: var(--dbv-kit-btn-border-style);
|
||||
--dbv-kit-icon-btn-border-color: var(--dbv-kit-btn-border-color);
|
||||
|
||||
/* Icon Button outline variables */
|
||||
--dbv-kit-icon-btn-outline-width: var(--dbv-kit-control-outline-width);
|
||||
--dbv-kit-icon-btn-outline-style: var(--dbv-kit-control-outline-style);
|
||||
--dbv-kit-icon-btn-outline-color: var(--dbv-kit-control-outline-color);
|
||||
--dbv-kit-icon-btn-outline-offset: var(--dbv-kit-control-outline-offset);
|
||||
|
||||
/* Default size */
|
||||
--dbv-kit-icon-btn-size: var(--dbv-kit-control-height-medium);
|
||||
|
||||
/* Default colors */
|
||||
--dbv-kit-icon-btn-foreground: var(--tw-color-gray-600);
|
||||
--dbv-kit-icon-btn-foreground-hover: var(--tw-color-gray-600);
|
||||
--dbv-kit-icon-btn-foreground-active: var(--tw-color-gray-700);
|
||||
--dbv-kit-icon-btn-background: transparent;
|
||||
--dbv-kit-icon-btn-background-hover: var(--tw-color-gray-100);
|
||||
--dbv-kit-icon-btn-background-active: var(--tw-color-gray-200);
|
||||
|
||||
/* Loader color */
|
||||
--dbv-kit-btn-loader-color: var(--dbv-kit-btn-foreground-hover);
|
||||
--dbv-kit-btn-loader-base-color: transparent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
@layer base {
|
||||
:root {
|
||||
--dbv-kit-icon-btn-small-size: var(--dbv-kit-control-height-small);
|
||||
--dbv-kit-icon-btn-medium-size: var(--dbv-kit-control-height-medium);
|
||||
--dbv-kit-icon-btn-large-size: var(--dbv-kit-control-height-large);
|
||||
--dbv-kit-icon-btn-xlarge-size: var(--dbv-kit-control-height-xlarge);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
@layer base {
|
||||
:root {
|
||||
/* Primary */
|
||||
--dbv-kit-icon-btn-primary-foreground: var(--tw-color-gray-600);
|
||||
--dbv-kit-icon-btn-primary-foreground-hover: var(--dbv-kit-color-primary-600);
|
||||
--dbv-kit-icon-btn-primary-foreground-active: var(--dbv-kit-color-primary-700);
|
||||
--dbv-kit-icon-btn-primary-background: transparent;
|
||||
--dbv-kit-icon-btn-primary-background-hover: var(--tw-color-gray-100);
|
||||
--dbv-kit-icon-btn-primary-background-active: var(--tw-color-gray-200);
|
||||
--dbv-kit-icon-btn-primary-loader-color: var(--tw-color-gray-300);
|
||||
|
||||
/* Secondary */
|
||||
--dbv-kit-icon-btn-secondary-foreground: var(--tw-color-gray-500);
|
||||
--dbv-kit-icon-btn-secondary-foreground-hover: var(--dbv-kit-color-primary-600);
|
||||
--dbv-kit-icon-btn-secondary-foreground-active: var(--dbv-kit-color-primary-700);
|
||||
--dbv-kit-icon-btn-secondary-background: transparent;
|
||||
--dbv-kit-icon-btn-secondary-background-hover: transparent;
|
||||
--dbv-kit-icon-btn-secondary-background-active: transparent;
|
||||
--dbv-kit-icon-btn-secondary-border-color: transparent;
|
||||
--dbv-kit-icon-btn-secondary-loader-color: var(--tw-color-gray-300);
|
||||
|
||||
/* Danger */
|
||||
--dbv-kit-icon-btn-danger-foreground: var(--tw-color-red-600);
|
||||
--dbv-kit-icon-btn-danger-foreground-hover: var(--tw-color-red-700);
|
||||
--dbv-kit-icon-btn-danger-foreground-active: var(--tw-color-red-800);
|
||||
--dbv-kit-icon-btn-danger-background: transparent;
|
||||
--dbv-kit-icon-btn-danger-background-hover: var(--tw-color-red-100);
|
||||
--dbv-kit-icon-btn-danger-background-active: var(--tw-color-red-200);
|
||||
--dbv-kit-icon-btn-danger-loader-color: var(--tw-color-red-300);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
@layer base {
|
||||
.dbv-kit-radio-group {
|
||||
display: flex;
|
||||
gap: calc(var(--dbv-kit-radio-gap) * 4);
|
||||
|
||||
&.dbv-kit-radio-group--vertical {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&:not(.dbv-kit-radio-group--vertical) .dbv-kit-radio {
|
||||
margin-inline-end: calc(var(--dbv-kit-radio-gap) * 4);
|
||||
gap: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ export function RadioGroup({ className, children, labelledBy, label, ['aria-labe
|
||||
</div>
|
||||
)}
|
||||
<_RadioGroup
|
||||
aria-labelledby={labelledById}
|
||||
aria-labelledby={ariaLabel ? undefined : labelledById}
|
||||
aria-label={ariaLabel}
|
||||
className={clsx('dbv-kit-radio-group', className, props.vertical && 'dbv-kit-radio-group--vertical')}
|
||||
>
|
||||
|
||||
@@ -20,19 +20,20 @@
|
||||
font-weight: var(--dbv-kit-select-font-weight);
|
||||
font-size: var(--dbv-kit-select-font-size);
|
||||
outline-width: var(--dbv-kit-control-outline-width);
|
||||
outline-offset: var(--dbv-kit-control-outline-offset);
|
||||
outline-color: var(--dbv-kit-control-outline-color);
|
||||
|
||||
&:hover {
|
||||
border-color: var(--dbv-kit-color-control-hover);
|
||||
&:hover:not(:disabled) {
|
||||
border-color: var(--dbv-kit-select-hover-border-color);
|
||||
}
|
||||
|
||||
&[aria-disabled='true'] {
|
||||
opacity: var(--dbv-kit-control-disabled-opacity);
|
||||
color: var(--dbv-kit-select-disabled-foreground);
|
||||
background-color: var(--dbv-kit-select-disabled-background);
|
||||
}
|
||||
&[data-focus-visible],
|
||||
&:focus-visible {
|
||||
outline-style: solid;
|
||||
outline-offset: var(--dbv-kit-control-outline-offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +75,8 @@
|
||||
.dbv-kit-select__item {
|
||||
display: block;
|
||||
width: 100%;
|
||||
font-weight: var(--dbv-kit-select-font-weight);
|
||||
font-size: var(--dbv-kit-select-font-size);
|
||||
padding-inline: var(--dbv-kit-select-item-padding-inline);
|
||||
padding-block: var(--dbv-kit-select-item-padding-block);
|
||||
text-align: left;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import { useState } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { SelectProvider, Select, SelectPopover, SelectItem, SelectLabel } from './Select.js';
|
||||
import { SelectProvider, Select, SelectPopover, SelectItem, SelectLabel, type SelectProviderProps } from './Select.js';
|
||||
import './SelectField.css';
|
||||
|
||||
export interface SelectItem<T> {
|
||||
@@ -57,6 +57,8 @@ export interface SelectFieldProps<T, ItemType = SelectItem<T>> {
|
||||
|
||||
className?: string;
|
||||
|
||||
noItemsPlaceholder?: React.ReactNode;
|
||||
|
||||
/**
|
||||
* Custom renderer for the selected value, overrides itemRenderer for the selected state
|
||||
* Only needed for special formatting of the selected value different from list items
|
||||
@@ -67,6 +69,16 @@ export interface SelectFieldProps<T, ItemType = SelectItem<T>> {
|
||||
* Custom arrow icon React Node that will be rendered instead default one
|
||||
*/
|
||||
arrowIcon?: React.ReactNode;
|
||||
|
||||
store?: SelectProviderProps['store'];
|
||||
|
||||
autoFocusItemsOnShow?: boolean;
|
||||
|
||||
'aria-labelledby'?: string,
|
||||
|
||||
'aria-label'?: string
|
||||
|
||||
id?: string;
|
||||
}
|
||||
|
||||
// Utility function to get value by it's key or using getter function
|
||||
@@ -82,13 +94,17 @@ export function SelectField<T, ItemType extends {} = SelectItem<T>>({
|
||||
itemRender,
|
||||
itemDisabled,
|
||||
label,
|
||||
noItemsPlaceholder = 'No items',
|
||||
description,
|
||||
disabled,
|
||||
required,
|
||||
className,
|
||||
selectedRender,
|
||||
arrowIcon,
|
||||
store,
|
||||
autoFocusItemsOnShow,
|
||||
name,
|
||||
id,
|
||||
}: SelectFieldProps<T, ItemType>) {
|
||||
const getItemValue = (item: ItemType): T =>
|
||||
getValueByPath<ItemType, T>(item, itemValue, i => ('value' in i ? (i as unknown as SelectItem<T>).value : (i as unknown as T)));
|
||||
@@ -115,29 +131,28 @@ export function SelectField<T, ItemType extends {} = SelectItem<T>>({
|
||||
|
||||
const selectedItem = items.find(item => getItemValue(item) === currentValue);
|
||||
|
||||
const displayValue = selectedItem ? (selectedRender ? selectedRender(currentValue, selectedItem) : renderItem(selectedItem)) : '';
|
||||
const displayValue = selectedRender ? selectedRender(currentValue, selectedItem) : selectedItem ? renderItem(selectedItem) : '';
|
||||
|
||||
return (
|
||||
<div className={clsx('dbv-kit-select-field', className)}>
|
||||
<SelectProvider value={currentValue as any} setValue={val => handleChange(val as T)}>
|
||||
<SelectProvider value={currentValue as any} setValue={val => handleChange(val as T)} store={store}>
|
||||
{label && <SelectLabel className={clsx(required && 'dbv-kit-select__label--required')}>{label}</SelectLabel>}
|
||||
|
||||
<Select name={name} disabled={disabled}>
|
||||
<Select id={id} name={name} disabled={disabled} required={required}>
|
||||
{displayValue}
|
||||
{arrowIcon ?? <Select.Arrow />}
|
||||
{arrowIcon ?? <Select.Arrow className='dbv-kit-select__arrow-icon' />}
|
||||
</Select>
|
||||
{description && <span className="dbv-kit-select__description">{description}</span>}
|
||||
|
||||
<SelectPopover gutter={4} unmountOnHide>
|
||||
<SelectPopover autoFocusOnShow={autoFocusItemsOnShow} gutter={4} unmountOnHide>
|
||||
{items.length === 0 ? (
|
||||
<div className="dbv-kit-select__empty">No items</div>
|
||||
<div className="dbv-kit-select__empty">{noItemsPlaceholder}</div>
|
||||
) : (
|
||||
items.map(item => (
|
||||
<SelectItem
|
||||
key={String(getItemValue(item))}
|
||||
value={getItemValue(item) as any}
|
||||
disabled={isItemDisabled(item)}
|
||||
className="dbv-kit-select__item"
|
||||
>
|
||||
{renderItem(item)}
|
||||
</SelectItem>
|
||||
|
||||
@@ -5,11 +5,14 @@
|
||||
|
||||
--dbv-kit-select-foreground: var(--dbv-kit-color-foreground);
|
||||
--dbv-kit-select-background: var(--dbv-kit-color-background);
|
||||
--dbv-kit-select-disabled-foreground: var(--dbv-kit-control-disabled-foreground);
|
||||
--dbv-kit-select-disabled-background: var(--dbv-kit-control-disabled-background);
|
||||
|
||||
--dbv-kit-select-border-width: var(--dbv-kit-control-border-width);
|
||||
--dbv-kit-select-border-color: var(--dbv-kit-color-control-inactive);
|
||||
--dbv-kit-select-border-style: solid;
|
||||
--dbv-kit-select-border-radius: var(--dbv-kit-control-border-radius);
|
||||
--dbv-kit-select-hover-border-color: var(--dbv-kit-color-control-hover);
|
||||
|
||||
--dbv-kit-select-font-weight: var(--tw-font-weight-normal);
|
||||
--dbv-kit-select-font-size: calc(var(--dbv-kit-font-size-base) * 0.875);
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
@import './_base.css';
|
||||
@import './_sizes.css';
|
||||
|
||||
@layer base {
|
||||
.dbv-kit-spinner {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: var(--dbv-kit-spinner-height);
|
||||
height: var(--dbv-kit-spinner-height);
|
||||
}
|
||||
|
||||
.dbv-kit-spinner--small {
|
||||
width: var(--dbv-kit-spinner-small-height);
|
||||
height: var(--dbv-kit-spinner-small-height);
|
||||
}
|
||||
|
||||
.dbv-kit-spinner--medium {
|
||||
width: var(--dbv-kit-spinner-medium-height);
|
||||
height: var(--dbv-kit-spinner-medium-height);
|
||||
}
|
||||
|
||||
.dbv-kit-spinner--large {
|
||||
width: var(--dbv-kit-spinner-large-height);
|
||||
height: var(--dbv-kit-spinner-large-height);
|
||||
}
|
||||
|
||||
.dbv-kit-spinner--xlarge {
|
||||
width: var(--dbv-kit-spinner-xlarge-height);
|
||||
height: var(--dbv-kit-spinner-xlarge-height);
|
||||
}
|
||||
|
||||
.dbv-kit-spinner__svg {
|
||||
stroke-dasharray: 40px, 100px;
|
||||
stroke-dashoffset: 5px;
|
||||
stroke-width: var(--dbv-kit-spinner-stroke-width);
|
||||
stroke: var(--dbv-kit-spinner-stroke-color);
|
||||
stroke-linecap: var(--dbv-kit-spinner-stroke-linecap);
|
||||
|
||||
animation: var(--dbv-kit-animate-spin);
|
||||
animation-delay: var(--dbv-kit-spinner-animation-delay);
|
||||
}
|
||||
|
||||
.dbv-kit-spinner__circle {
|
||||
animation: var(--dbv-kit-animate-stroke);
|
||||
animation-delay: var(--dbv-kit-spinner-animation-delay);
|
||||
|
||||
@media screen and (prefers-reduced-motion: reduce) {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import clsx from 'clsx';
|
||||
import './Spinner.css';
|
||||
import type { ControlSize } from '../types/controls.js';
|
||||
|
||||
export interface SpinnerProps {
|
||||
active?: boolean;
|
||||
className?: string;
|
||||
size?: ControlSize;
|
||||
}
|
||||
|
||||
export function Spinner({ className, size, active = true }: SpinnerProps) {
|
||||
if (!active) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<span className={clsx('dbv-kit-spinner', size && `dbv-kit-spinner--${size}`, className)}>
|
||||
<svg className="dbv-kit-spinner__svg" viewBox="11 11 22 22">
|
||||
<circle className="dbv-kit-spinner__circle" cx="22" cy="22" r="9" fill="none"></circle>
|
||||
</svg>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
@keyframes stroke {
|
||||
0% {
|
||||
stroke-dasharray: 1px, 100px;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
50% {
|
||||
stroke-dasharray: 45px, 100px;
|
||||
stroke-dashoffset: -10px;
|
||||
}
|
||||
100% {
|
||||
stroke-dasharray: 17px, 100px;
|
||||
stroke-dashoffset: -58px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spinning {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--dbv-kit-spinner-height: var(--dbv-kit-control-height-medium);
|
||||
--dbv-kit-spinner-animation-duration: 1.8s;
|
||||
--dbv-kit-spinner-animation-delay: -0.3s;
|
||||
|
||||
--dbv-kit-spinner-stroke-width: 2.5px;
|
||||
--dbv-kit-spinner-stroke-color: var(--dbv-kit-color-primary-600);
|
||||
--dbv-kit-spinner-stroke-linecap: butt;
|
||||
|
||||
--dbv-kit-animate-stroke: stroke var(--dbv-kit-spinner-animation-duration) linear infinite;
|
||||
--dbv-kit-animate-spin: spinning var(--dbv-kit-spinner-animation-duration) cubic-bezier(0.455, 0.03, 0.515, 0.955) infinite;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
@layer base {
|
||||
:root {
|
||||
--dbv-kit-spinner-small-height: var(--dbv-kit-control-height-small);
|
||||
--dbv-kit-spinner-medium-height: var(--dbv-kit-control-height-medium);
|
||||
--dbv-kit-spinner-large-height: var(--dbv-kit-control-height-large);
|
||||
--dbv-kit-spinner-xlarge-height: var(--dbv-kit-control-height-xlarge);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@
|
||||
--dbv-kit-control-border-radius: var(--tw-radius-sm);
|
||||
--dbv-kit-control-border-width: 1px;
|
||||
--dbv-kit-control-disabled-opacity: 0.5;
|
||||
--dbv-kit-control-disabled-foreground: var(--tw-color-gray-400);
|
||||
--dbv-kit-control-disabled-background: var(--tw-color-gray-200);
|
||||
|
||||
/* Outline */
|
||||
--dbv-kit-control-outline-color: var(--tw-color-blue-500);
|
||||
|
||||
@@ -21,7 +21,8 @@ export {
|
||||
type FocusTrapRegionProps,
|
||||
} from '@ariakit/react';
|
||||
|
||||
export { Button, ButtonBase, type ButtonProps } from './Button/Button.js';
|
||||
export { Button, ButtonBase, type ButtonProps, ButtonIcon, type ButtonIconProps } from './Button/Button.js';
|
||||
export { IconButton, IconButtonBase, type IconButtonProps } from './IconButton/IconButton.js';
|
||||
export { Checkbox, CheckboxBase, type CheckboxProps } from './Checkbox/Checkbox.js';
|
||||
export { Input, InputBase, type InputProps } from './Input/Input.js';
|
||||
export {
|
||||
@@ -35,6 +36,8 @@ export {
|
||||
type SelectItemProps,
|
||||
} from './Select/Select.js';
|
||||
export { SelectField, type SelectFieldProps, type SelectItem } from './Select/SelectField.js';
|
||||
export { Spinner, type SpinnerProps } from './Spinner/Spinner.js';
|
||||
export { Radio, RadioGroup, useRadioContext, useRadioStore, type RadioProviderProps, type RadioProps, type RadioGroupProps } from './Radio/index.js';
|
||||
export { Icon, type IconProps } from './Icon/Icon.js';
|
||||
export * from './utils/clsx.js';
|
||||
export * from './ComponentProvider.js';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Story } from '@ladle/react';
|
||||
import { Button, type ButtonProps } from '../../../index.js';
|
||||
import { Button, type ButtonProps, ButtonIcon } from '../../../index.js';
|
||||
import { useState } from 'react';
|
||||
|
||||
export { Tokens } from './button-tokens.js';
|
||||
@@ -48,17 +48,24 @@ export const Variants = () => (
|
||||
<code><Button variant="primary"/></code>
|
||||
</div>
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<Button loading>Loading</Button>
|
||||
<Button>Primary</Button>
|
||||
<Button disabled>Disabled</Button>
|
||||
</div>
|
||||
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<Button variant="secondary" loading>
|
||||
Secondary
|
||||
</Button>
|
||||
<Button variant="secondary">Secondary</Button>
|
||||
<Button variant="secondary" disabled>
|
||||
Disabled
|
||||
</Button>
|
||||
</div>
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<Button variant="danger" loading>
|
||||
Danger
|
||||
</Button>
|
||||
<Button variant="danger">Danger</Button>
|
||||
<Button variant="danger" disabled>
|
||||
Disabled
|
||||
@@ -136,10 +143,10 @@ export const Sizes = () => (
|
||||
export const Icons = () => (
|
||||
<div>
|
||||
<h2>Icons</h2>
|
||||
<h3><Button.Icon></h3>
|
||||
<h3><ButtonIcon></h3>
|
||||
<code>.dbv-kit-button__icon</code>
|
||||
<p>
|
||||
To properly place an icon inside a button, you have to use Button.Icon component. That component will compensate outer padding to balance the
|
||||
To properly place an icon inside a button, you have to use ButtonIcon component. That component will compensate outer padding to balance the
|
||||
button view. You need to specify the placement property to adjust the icon position.
|
||||
</p>
|
||||
<dl>
|
||||
@@ -148,7 +155,7 @@ export const Icons = () => (
|
||||
</dl>
|
||||
<div className="codeblock">
|
||||
<code>
|
||||
<Button> <br /> <Button.Icon placement="start"/>
|
||||
<Button> <br /> <ButtonIcon placement="start"/>
|
||||
<br />
|
||||
Text
|
||||
<br /> <Button/>
|
||||
@@ -159,14 +166,14 @@ export const Icons = () => (
|
||||
<h4>Compare buttons:</h4>
|
||||
<div className="tw:flex tw:gap-4 tw:items-center tw:my-4">
|
||||
<Button variant="secondary">
|
||||
<Button.Icon placement="start">🧤</Button.Icon>
|
||||
<ButtonIcon placement="start">🧤</ButtonIcon>
|
||||
Text
|
||||
</Button>
|
||||
<Button variant="secondary">🧤 Text</Button>
|
||||
</div>
|
||||
<p>
|
||||
The left button uses Button.Icon component and looks more balanced. If you feel that in your case it's not needed, feel free to not use the
|
||||
<b> Button.Icon </b> component.
|
||||
The left button uses ButtonIcon component and looks more balanced. If you feel that in your case it's not needed, feel free to not use the
|
||||
<b> ButtonIcon </b> component.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -183,12 +190,12 @@ export const Icons = () => (
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<Button size="small">
|
||||
Love
|
||||
<Button.Icon placement="end">❤️</Button.Icon>
|
||||
<ButtonIcon placement="end">❤️</ButtonIcon>
|
||||
</Button>
|
||||
|
||||
<Button className="tw:text-lime-300">
|
||||
Have you seen
|
||||
<Button.Icon className="w-2">
|
||||
<ButtonIcon className="w-2">
|
||||
<svg width="16" height="16" fill="none">
|
||||
<g strokeWidth="0"></g>
|
||||
<g strokeLinecap="round" strokeLinejoin="round"></g>
|
||||
@@ -201,24 +208,24 @@ export const Icons = () => (
|
||||
></path>
|
||||
</g>
|
||||
</svg>
|
||||
</Button.Icon>
|
||||
</ButtonIcon>
|
||||
UFO?
|
||||
</Button>
|
||||
|
||||
<Button size="large">
|
||||
<Button.Icon placement="start">🎾</Button.Icon>
|
||||
<ButtonIcon placement="start">🎾</ButtonIcon>
|
||||
Tennis
|
||||
</Button>
|
||||
|
||||
<Button size="xlarge">
|
||||
<Button.Icon placement="start">🎾</Button.Icon>
|
||||
<ButtonIcon placement="start">🎾</ButtonIcon>
|
||||
Tennis is Love
|
||||
<Button.Icon placement="end">❤️</Button.Icon>
|
||||
<ButtonIcon placement="end">❤️</ButtonIcon>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<Button loading>
|
||||
<Button.Icon className="tw:w-8 tw:h-4" placement="start">
|
||||
<ButtonIcon className="tw:w-8 tw:h-4" placement="start">
|
||||
<svg width="16" height="16" fill="none">
|
||||
<g strokeWidth="0"></g>
|
||||
<g strokeLinecap="round" strokeLinejoin="round"></g>
|
||||
@@ -231,34 +238,34 @@ export const Icons = () => (
|
||||
></path>
|
||||
</g>
|
||||
</svg>
|
||||
</Button.Icon>
|
||||
</ButtonIcon>
|
||||
UFO
|
||||
</Button>
|
||||
<Button variant="secondary" loading>
|
||||
<Button.Icon placement="start">🎾</Button.Icon>
|
||||
<ButtonIcon placement="start">🎾</ButtonIcon>
|
||||
Tennis
|
||||
</Button>
|
||||
<Button disabled>
|
||||
<Button.Icon placement="start">🎾</Button.Icon>
|
||||
<ButtonIcon placement="start">🎾</ButtonIcon>
|
||||
Tennis
|
||||
</Button>
|
||||
<Button variant="danger">
|
||||
<Button.Icon placement="start">🎾</Button.Icon>
|
||||
<ButtonIcon placement="start">🎾</ButtonIcon>
|
||||
Tennis
|
||||
</Button>
|
||||
<Button>
|
||||
<Button.Icon>🎾</Button.Icon>
|
||||
<ButtonIcon>🎾</ButtonIcon>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const CustomLoader = () => (
|
||||
<Button.Icon placement="start">
|
||||
<div>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" className="tw:animate-spin tw:p-1">
|
||||
<circle cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeDasharray="31.415, 31.415" />
|
||||
</svg>
|
||||
</Button.Icon>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const Loading = () => {
|
||||
@@ -280,9 +287,7 @@ export const Loading = () => {
|
||||
and one of the dark colors for dark theme.
|
||||
</span>
|
||||
</p>
|
||||
<div>
|
||||
<code>--dbv-kit-btn-loader-animation:</code> var(--animate-spin); <span className="comment"> Button loader animation</span>
|
||||
</div>
|
||||
|
||||
<label>
|
||||
Enable loaders <input type="checkbox" checked={loading} onChange={toggleLoading} />
|
||||
</label>
|
||||
|
||||
@@ -61,9 +61,13 @@ export const States = () => {
|
||||
</Checkbox>
|
||||
<Button onClick={() => setIndeterminate(prev => !prev)}>Set Indeterminate</Button>
|
||||
<Checkbox indeterminate={indeterminate}>Indeterminate</Checkbox>
|
||||
<Checkbox indeterminate={indeterminate} indeterminateIcon={<div className="tw:flex tw:relative tw:-top-[1px] tw:font-bold">▫</div>}>
|
||||
<Checkbox
|
||||
indeterminate={indeterminate}
|
||||
indeterminateIcon={<div className="tw:flex tw:relative tw:-top-[2px] tw:-left-[1px] tw:font-bold">▫</div>}
|
||||
>
|
||||
Indeterminate Custom
|
||||
</Checkbox>
|
||||
Long text example:
|
||||
<Checkbox>
|
||||
Insert spaces when pressing <code>Tab</code>. This setting is overridden based on the file contents when{' '}
|
||||
<a data-href="#" href="#">
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
import { Button, ButtonIcon, Icon, type IconProps } from '../../../index.js';
|
||||
|
||||
// All available icon names from the IconNames type
|
||||
const iconNames = [
|
||||
'replace',
|
||||
'replace-all',
|
||||
'match-word',
|
||||
'case',
|
||||
'regex',
|
||||
'sort-asc',
|
||||
'sort-desc',
|
||||
'cross',
|
||||
'sort-unknown',
|
||||
'arrow-up',
|
||||
'arrow-down',
|
||||
] as Array<IconProps['name']>;
|
||||
|
||||
const sizes = ['small', 'medium', 'large'] as const;
|
||||
|
||||
export function Documentation() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Icon</h1>
|
||||
<p>Icon component for displaying SVG icons using the symbol/use pattern.</p>
|
||||
<h2>Usage</h2>
|
||||
<p>Use the Icon component to display predefined SVG icons in your application.</p>
|
||||
<h2>Anatomy</h2>
|
||||
<p>
|
||||
The Icon component consists of an SVG element that references icon symbols via the <code><use></code> element. Icons are sized
|
||||
automatically based on the size prop and support color customization.
|
||||
</p>
|
||||
<pre className="codeblock">
|
||||
{`
|
||||
<svg class="dbv-kit-icon" width="16" height="16" viewBox="0 0 16 16">
|
||||
<use href="#icon-search_sm" />
|
||||
</svg>
|
||||
`}
|
||||
</pre>
|
||||
<h2>Class names</h2>
|
||||
<p>
|
||||
The Icon component uses the following class names:
|
||||
<ul>
|
||||
<li>
|
||||
<code>dbv-kit-icon</code>: Base class for the icon.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h2>Props</h2>
|
||||
<table className="tw:table tw:w-full tw:border-collapse">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="tw:py-2 tw:border tw:px-2">Prop</th>
|
||||
<th className="tw:py-2 tw:border tw:px-2">Type</th>
|
||||
<th className="tw:py-2 tw:border tw:px-2">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="tw:border tw:p-2">name</td>
|
||||
<td className="tw:border tw:p-2">
|
||||
<pre>IconNames (required)</pre>
|
||||
</td>
|
||||
<td className="tw:border tw:p-2">The name of the icon to display.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="tw:border tw:p-2">size</td>
|
||||
<td className="tw:border tw:p-2">
|
||||
<pre>small | medium | large</pre>
|
||||
</td>
|
||||
<td className="tw:border tw:p-2">Size of the icon. Default is 'small'.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="tw:border tw:p-2">className</td>
|
||||
<td className="tw:border tw:p-2">
|
||||
<pre>string | undefined</pre>
|
||||
</td>
|
||||
<td className="tw:border tw:p-2">Additional CSS class name.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="tw:border tw:p-2">color</td>
|
||||
<td className="tw:border tw:p-2">
|
||||
<pre>string | undefined</pre>
|
||||
</td>
|
||||
<td className="tw:border tw:p-2">Color of the icon.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="tw:border tw:p-2">style</td>
|
||||
<td className="tw:border tw:p-2">
|
||||
<pre>React.CSSProperties | undefined</pre>
|
||||
</td>
|
||||
<td className="tw:border tw:p-2">Inline styles for the icon.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function AllIcons() {
|
||||
return (
|
||||
<div>
|
||||
<h1>All Available Icons</h1>
|
||||
<p>Here are all the available icons in the default (small) size:</p>
|
||||
<div className="tw:grid tw:grid-cols-4 tw:gap-4 tw:mt-4">
|
||||
{iconNames.map(iconName => (
|
||||
<div key={iconName} className="tw:flex tw:flex-col tw:items-center tw:p-4">
|
||||
<Icon name={iconName} />
|
||||
<code className="tw:text-xs tw:mt-2">{iconName}</code>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function Sizes() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Icon Sizes</h1>
|
||||
<p>Icons come in three different sizes: small (16px), medium (24px), and large (32px).</p>
|
||||
<div className="tw:space-y-6 tw:mt-4">
|
||||
{sizes.map(size => (
|
||||
<div key={size} className="tw:space-y-2">
|
||||
<h3 className="tw:text-lg tw:font-semibold tw:capitalize">
|
||||
{size} ({size === 'small' ? '16px' : size === 'medium' ? '24px' : '32px'})
|
||||
</h3>
|
||||
<div className="tw:flex tw:gap-4 tw:flex-wrap">
|
||||
{iconNames.map(iconName => (
|
||||
<div key={`${size}-${iconName}`} className="tw:flex tw:flex-col tw:items-center tw:p-2">
|
||||
<Icon name={iconName} size={size} />
|
||||
<code className="tw:text-xs tw:mt-1">{iconName}</code>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function WithColors() {
|
||||
const colors = ['red', 'green', 'blue'];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Icons with Colors</h1>
|
||||
<p>Icons can be customized with different colors using the color prop.</p>
|
||||
<div className="tw:space-y-4 tw:mt-4">
|
||||
{colors.map(color => (
|
||||
<div key={color} className="tw:space-y-2">
|
||||
<h3 className="tw:text-lg tw:font-semibold" style={{ color }}>
|
||||
Color: {color}
|
||||
</h3>
|
||||
<div className="tw:flex tw:gap-4 tw:flex-wrap">
|
||||
{iconNames.slice(0, 5).map(iconName => (
|
||||
<div key={`${color}-${iconName}`} className="tw:flex tw:flex-col tw:items-center tw:p-2 tw:border tw:rounded">
|
||||
<Icon name={iconName} size="medium" color={color} />
|
||||
<code className="tw:text-xs tw:mt-1">{iconName}</code>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function UsageExamples() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Usage Examples</h1>
|
||||
<div className="tw:space-y-6 tw:mt-4">
|
||||
<div>
|
||||
<h3 className="tw:text-lg tw:font-semibold">In Buttons</h3>
|
||||
<Button>
|
||||
<ButtonIcon placement="start">
|
||||
<Icon name="cross" size="medium" color="white" className="tw:h-4 tw:w-4" />
|
||||
</ButtonIcon>
|
||||
Close
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="tw:text-lg tw:font-semibold">As Status Indicators</h3>
|
||||
<div className="tw:space-y-2">
|
||||
<div className="tw:flex tw:items-center tw:gap-2">
|
||||
<Icon name="sort-asc" size="medium" color="green" />
|
||||
<span>Sorted ascending</span>
|
||||
</div>
|
||||
<div className="tw:flex tw:items-center tw:gap-2">
|
||||
<Icon name="sort-desc" size="medium" color="red" />
|
||||
<span>Sorted descending</span>
|
||||
</div>
|
||||
<div className="tw:flex tw:items-center tw:gap-2">
|
||||
<Icon name="sort-unknown" size="medium" color="gray" />
|
||||
<span>Unsorted</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="tw:text-lg tw:font-semibold">With Custom Styling</h3>
|
||||
<div className="tw:flex tw:items-center tw:gap-4">
|
||||
<Icon
|
||||
name="replace"
|
||||
size="large"
|
||||
style={{
|
||||
filter: 'drop-shadow(2px 2px 4px rgba(0,0,0,0.2))',
|
||||
transform: 'rotate(15deg)',
|
||||
}}
|
||||
/>
|
||||
<Icon name="regex" size="medium" className="tw:opacity-50 tw:hover:opacity-100 tw:transition-opacity" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
import { useState } from 'react';
|
||||
import { IconButton } from '../../../index.js';
|
||||
|
||||
const example = `<IconButton
|
||||
variant="primary" | "secondary" | "danger"
|
||||
size="small" | "medium" | "large" | "xlarge"
|
||||
loading={boolean}
|
||||
disabled={boolean}
|
||||
onClick={function}
|
||||
aria-label="string"
|
||||
>
|
||||
{icon}
|
||||
</IconButton>`;
|
||||
|
||||
export const Documentation = () => {
|
||||
return (
|
||||
<div className="tw:space-y-4">
|
||||
<h1 className="tw:text-2xl tw:font-bold">IconButton</h1>
|
||||
<p>IconButton is a button component that displays an icon. It supports various sizes and styles, and can be disabled or in a loading state.</p>
|
||||
|
||||
<pre className="codeblock">{example}</pre>
|
||||
|
||||
<h2 className="tw:text-xl tw:font-semibold">Classnames</h2>
|
||||
<ul className="tw:list-disc tw:pl-5">
|
||||
<li>
|
||||
<code>dbv-kit-icon-button</code> - Main component class
|
||||
</li>
|
||||
<li>
|
||||
<code>dbv-kit-icon-button--primary/secondary/danger</code> - Variant classes
|
||||
</li>
|
||||
<li>
|
||||
<code>dbv-kit-icon-button--small/medium/large/xlarge</code> - Size classes
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2 className="tw:text-xl tw:font-semibold">CSS Tokens</h2>
|
||||
<div className="tw:p-4 tw:rounded-md tw:overflow-auto">
|
||||
<h3 className="tw:font-medium">Structure</h3>
|
||||
<ul className="tw:pl-5 tw:mb-2">
|
||||
<li>
|
||||
<code>--dbv-kit-icon-btn-border-radius</code> - Controls button corner roundness
|
||||
</li>
|
||||
<li>
|
||||
<code>--dbv-kit-icon-btn-border-width/style/color</code> - Border properties
|
||||
</li>
|
||||
<li>
|
||||
<code>--dbv-kit-icon-btn-size</code> - Default button size (medium)
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="tw:font-medium">Focus State</h3>
|
||||
<ul className="tw:pl-5 tw:mb-2">
|
||||
<li>
|
||||
<code>--dbv-kit-icon-btn-outline-color/offset</code> - Focus outline appearance
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 className="tw:font-medium">Colors</h3>
|
||||
<ul className="tw:pl-5">
|
||||
<li>
|
||||
<code>--dbv-kit-icon-btn-foreground/background</code> - Default state colors
|
||||
</li>
|
||||
<li>
|
||||
<code>--dbv-kit-icon-btn-foreground/background-hover</code> - Hover state colors
|
||||
</li>
|
||||
<li>
|
||||
<code>--dbv-kit-icon-btn-foreground/background-active</code> - Active state colors
|
||||
</li>
|
||||
<li>
|
||||
<code>--dbv-kit-btn-loader-color/base-color</code> - Loading spinner colors
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const IconButtons = () => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const handleClick = () => {
|
||||
setIsLoading(true);
|
||||
setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
}, 5000);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="tw:flex tw:flex-col tw:gap-4 tw:my-4 tw:items-center">
|
||||
<div>
|
||||
<h2>Primary</h2>
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<IconButton variant="primary" size="small" aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
<IconButton variant="primary" size="medium" aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
<IconButton variant="primary" size="large" aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
<IconButton variant="primary" size="xlarge" aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2>Secondary</h2>
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<IconButton variant="secondary" size="small" aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
<IconButton variant="secondary" size="medium" aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
<IconButton variant="secondary" size="large" aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
<IconButton variant="secondary" size="xlarge" aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2>Danger</h2>
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<IconButton variant="danger" size="small" aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
<IconButton variant="danger" size="medium" aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
<IconButton variant="danger" size="large" aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
<IconButton variant="danger" size="xlarge" aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2>Disabled</h2>
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<IconButton variant="primary" size="small" disabled aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
<IconButton variant="secondary" size="medium" disabled aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
<IconButton variant="danger" size="large" disabled aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
</div>
|
||||
<h2>Loading</h2>
|
||||
<div className="tw:flex tw:gap-4 tw:my-4 tw:items-center">
|
||||
<IconButton variant="primary" size="small" loading aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
<IconButton variant="secondary" loading={isLoading} onClick={handleClick} aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
<IconButton size="large" loading={isLoading} onClick={handleClick} aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
<IconButton variant="danger" size="xlarge" loading={isLoading} onClick={handleClick} aria-label="Add item">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<circle cx="12" cy="12" r="12" fill="currentColor" />
|
||||
</svg>
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
.customLoader {
|
||||
--dbv-kit-spinner-stroke-color: orange;
|
||||
--dbv-kit-spinner-animation-duration: 5s;
|
||||
--dbv-kit-animate-stroke: stroke var(--dbv-kit-spinner-animation-duration) linear infinite;
|
||||
--dbv-kit-animate-spin: spinning var(--dbv-kit-spinner-animation-duration) cubic-bezier(0.455, 0.03, 0.515, 0.955) infinite;
|
||||
--dbv-kit-spinner-stroke-linecap: round;
|
||||
}
|
||||