tsp-form 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +7 -0
- package/dist/index.js +2 -0
- package/dist/index.js.LICENSE.txt +9 -0
- package/package.json +47 -0
- package/src/components/Button.tsx +59 -0
- package/src/components/Chevron.tsx +84 -0
- package/src/components/ExpandablePanel.tsx +39 -0
- package/src/example/ExampleButtons.tsx +131 -0
- package/src/example/components/ContentPanel.tsx +12 -0
- package/src/example/example.css +83 -0
- package/src/example/index.html +12 -0
- package/src/example/index.tsx +21 -0
- package/src/example/styles/components.css +14 -0
- package/src/example/styles/utils.css +23 -0
- package/src/global.css +2 -0
- package/src/index.ts +3 -0
- package/src/styles/button.css +119 -0
- package/src/styles/chevron.css +19 -0
- package/src/styles/collapsible-panel.css +48 -0
- package/src/styles/form.css +47 -0
- package/tsconfig.json +19 -0
- package/webpack.config.js +107 -0
package/.babelrc
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! For license information please see index.js.LICENSE.txt */
|
|
2
|
+
!function(r,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("react"),require("clsx")):"function"==typeof define&&define.amd?define("MyUIComponents",["react","clsx"],e):"object"==typeof exports?exports.MyUIComponents=e(require("react"),require("clsx")):r.MyUIComponents=e(r.React,r.clsx)}(this,(r,e)=>(()=>{"use strict";var n={12:e=>{e.exports=r},56:(r,e,n)=>{r.exports=function(r){var e=n.nc;e&&r.setAttribute("nonce",e)}},72:r=>{var e=[];function n(r){for(var n=-1,t=0;t<e.length;t++)if(e[t].identifier===r){n=t;break}return n}function t(r,t){for(var a={},c=[],i=0;i<r.length;i++){var l=r[i],s=t.base?l[0]+t.base:l[0],u=a[s]||0,f="".concat(s," ").concat(u);a[s]=u+1;var p=n(f),d={css:l[1],media:l[2],sourceMap:l[3],supports:l[4],layer:l[5]};if(-1!==p)e[p].references++,e[p].updater(d);else{var v=o(d,t);t.byIndex=i,e.splice(i,0,{identifier:f,updater:v,references:1})}c.push(f)}return c}function o(r,e){var n=e.domAPI(e);return n.update(r),function(e){if(e){if(e.css===r.css&&e.media===r.media&&e.sourceMap===r.sourceMap&&e.supports===r.supports&&e.layer===r.layer)return;n.update(r=e)}else n.remove()}}r.exports=function(r,o){var a=t(r=r||[],o=o||{});return function(r){r=r||[];for(var c=0;c<a.length;c++){var i=n(a[c]);e[i].references--}for(var l=t(r,o),s=0;s<a.length;s++){var u=n(a[s]);0===e[u].references&&(e[u].updater(),e.splice(u,1))}a=l}}},113:r=>{r.exports=function(r,e){if(e.styleSheet)e.styleSheet.cssText=r;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(r))}}},314:r=>{r.exports=function(r){var e=[];return e.toString=function(){return this.map(function(e){var n="",t=void 0!==e[5];return e[4]&&(n+="@supports (".concat(e[4],") {")),e[2]&&(n+="@media ".concat(e[2]," {")),t&&(n+="@layer".concat(e[5].length>0?" ".concat(e[5]):""," {")),n+=r(e),t&&(n+="}"),e[2]&&(n+="}"),e[4]&&(n+="}"),n}).join("")},e.i=function(r,n,t,o,a){"string"==typeof r&&(r=[[null,r,void 0]]);var c={};if(t)for(var i=0;i<this.length;i++){var l=this[i][0];null!=l&&(c[l]=!0)}for(var s=0;s<r.length;s++){var u=[].concat(r[s]);t&&c[u[0]]||(void 0!==a&&(void 0===u[5]||(u[1]="@layer".concat(u[5].length>0?" ".concat(u[5]):""," {").concat(u[1],"}")),u[5]=a),n&&(u[2]?(u[1]="@media ".concat(u[2]," {").concat(u[1],"}"),u[2]=n):u[2]=n),o&&(u[4]?(u[1]="@supports (".concat(u[4],") {").concat(u[1],"}"),u[4]=o):u[4]="".concat(o)),e.push(u))}},e}},405:(r,e,n)=>{n.d(e,{A:()=>i});var t=n(601),o=n.n(t),a=n(314),c=n.n(a)()(o());c.push([r.id,".cpanel {\n border: 1px solid var(--color-line);\n border-radius: var(--radius-control);\n overflow: hidden;\n}\n\n.cpanel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n text-align: left;\n border-bottom: 1px solid var(--color-line);\n}\n\n.cpanel-header-title {\n padding: var(--spacing-title-y) var(--spacing-title-x);\n letter-spacing: var(--text-title--letter-spacing);\n font-size: var(--text-title);\n line-height: var(--text-title--line-height);\n font-weight: var(--text-title--font-weight);\n}\n\n.cpanel-header:focus {\n outline: none;\n}\n\n.cpanel-header:focus-visible {\n box-shadow: 0 0 0 1px var(--color-primary);\n}\n\n.cpanel-chevron {\n flex-shrink: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n width: var(--spacing-title-h);\n height: var(--spacing-title-h);\n border-left: var(--spacing-line) solid var(--color-line);\n cursor: pointer;\n}\n\n.cpanel-content.open {\n display: block;\n}\n\n.cpanel-content {\n display: none;\n}",""]);const i=c},525:(r,e,n)=>{n.d(e,{A:()=>i});var t=n(601),o=n.n(t),a=n(314),c=n.n(a)()(o());c.push([r.id,".rotate-0 {\n transform: rotate(0deg);\n}\n\n.rotate-90 {\n transform: rotate(90deg);\n}\n\n.rotate-180 {\n transform: rotate(180deg);\n}\n\n.-rotate-90 {\n transform: rotate(-90deg);\n}\n\n.chevron-animated {\n transition: transform 200ms ease-out;\n}",""]);const i=c},540:r=>{r.exports=function(r){var e=document.createElement("style");return r.setAttributes(e,r.attributes),r.insert(e,r.options),e}},601:r=>{r.exports=function(r){return r[1]}},659:r=>{var e={};r.exports=function(r,n){var t=function(r){if(void 0===e[r]){var n=document.querySelector(r);if(window.HTMLIFrameElement&&n instanceof window.HTMLIFrameElement)try{n=n.contentDocument.head}catch(r){n=null}e[r]=n}return e[r]}(r);if(!t)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");t.appendChild(n)}},698:(r,e)=>{var n=Symbol.for("react.transitional.element");function t(r,e,t){var o=null;if(void 0!==t&&(o=""+t),void 0!==e.key&&(o=""+e.key),"key"in e)for(var a in t={},e)"key"!==a&&(t[a]=e[a]);else t=e;return e=t.ref,{$$typeof:n,type:r,key:o,ref:void 0!==e?e:null,props:t}}Symbol.for("react.fragment"),e.jsx=t,e.jsxs=t},825:r=>{r.exports=function(r){if("undefined"==typeof document)return{update:function(){},remove:function(){}};var e=r.insertStyleElement(r);return{update:function(n){!function(r,e,n){var t="";n.supports&&(t+="@supports (".concat(n.supports,") {")),n.media&&(t+="@media ".concat(n.media," {"));var o=void 0!==n.layer;o&&(t+="@layer".concat(n.layer.length>0?" ".concat(n.layer):""," {")),t+=n.css,o&&(t+="}"),n.media&&(t+="}"),n.supports&&(t+="}");var a=n.sourceMap;a&&"undefined"!=typeof btoa&&(t+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(a))))," */")),e.styleTagTransform(t,r,e.options)}(e,r,n)},remove:function(){!function(r){if(null===r.parentNode)return!1;r.parentNode.removeChild(r)}(e)}}}},848:(r,e,n)=>{r.exports=n(698)},894:r=>{r.exports=e},998:(r,e,n)=>{n.d(e,{A:()=>i});var t=n(601),o=n.n(t),a=n(314),c=n.n(a)()(o());c.push([r.id,".btn {\n --color-text: var(--color-fg);\n --color-bg: var(--color-surface);\n --color-border: var(--color-surface);\n --color-bg-hover: var(--color-fg);\n --color-border-hover: var(--color-fg);\n --color-text-hover: var(--color-fg-contrast);\n padding: var(--spacing-control-y) var(--spacing-control-x);\n border-radius: var(--radius-control);\n border: 1px solid var(--color-border);\n cursor: pointer;\n background: var(--color-bg);\n color: var(--color-text);\n transition: all 0.2s ease-in-out;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n}\n\n.btn:hover {\n background: var(--color-bg-hover);\n border-color: var(--color-border-hover);\n color: var(--color-text-hover);\n}\n\n.btn.disabled {\n opacity: 0.5;\n pointer-events: none;\n}\n\n.btn-sm {\n padding: var(--spacing-control-compact-y) var(--spacing-control-compact-x);\n}\n\n.btn-lg {\n padding: var(--spacing-control-relaxed-y) var(--spacing-control-relaxed-x);\n}\n\n.btn-primary {\n --color-text: var(--color-primary-contrast);\n --color-bg: var(--color-primary);\n --color-border: var(--color-primary);\n}\n\n.btn-secondary {\n --color-text: var(--color-secondary-contrast);\n --color-bg: var(--color-secondary);\n --color-border: var(--color-secondary);\n}\n\n.btn-danger {\n --color-text: var(--color-danger-contrast);\n --color-bg: var(--color-danger);\n --color-border: var(--color-danger);\n}\n\n.btn-outline-default {\n --color-text: var(--color-fg);\n --color-bg: transparent;\n --color-border: var(--color-line);\n}\n\n.btn-outline-primary {\n --color-text: var(--color-primary);\n --color-border: var(--color-primary);\n --color-text-hover: var(--color-primary-contrast);\n --color-bg-hover: var(--color-primary);\n --color-border-hover: var(--color-primary);\n}\n\n.btn-outline-secondary {\n --color-text: var(--color-secondary);\n --color-border: var(--color-secondary);\n --color-text-hover: var(--color-secondary-contrast);\n --color-bg-hover: var(--color-secondary);\n --color-border-hover: var(--color-secondary);\n}\n\n.btn-outline-danger {\n --color-text: var(--color-danger);\n --color-border: var(--color-danger);\n --color-text-hover: var(--color-danger-contrast);\n --color-bg-hover: var(--color-danger);\n --color-border-hover: var(--color-danger);\n}\n\n.btn-ghost-default {\n --color-text: var(--color-fg);\n --color-bg: transparent;\n --color-border: transparent;\n --color-text-hover: var(--color-fg);\n --color-bg-hover: var(--color-surface);\n --color-border-hover: var(--color-surface);\n}\n\n.btn-ghost-primary {\n --color-text: var(--color-primary);\n --color-bg: transparent;\n --color-border: transparent;\n --color-text-hover: var(--color-fg);\n --color-bg-hover: var(--color-surface);\n --color-border-hover: var(--color-surface);\n}\n\n.btn-ghost-secondary {\n --color-text: var(--color-secondary);\n --color-bg: transparent;\n --color-border: transparent;\n --color-text-hover: var(--color-fg);\n --color-bg-hover: var(--color-surface);\n --color-border-hover: var(--color-surface);\n}\n\n.btn-ghost-danger {\n --color-text: var(--color-danger);\n --color-bg: transparent;\n --color-border: transparent;\n}\n",""]);const i=c}},t={};function o(r){var e=t[r];if(void 0!==e)return e.exports;var a=t[r]={id:r,exports:{}};return n[r](a,a.exports,o),a.exports}o.n=r=>{var e=r&&r.__esModule?()=>r.default:()=>r;return o.d(e,{a:e}),e},o.d=(r,e)=>{for(var n in e)o.o(e,n)&&!o.o(r,n)&&Object.defineProperty(r,n,{enumerable:!0,get:e[n]})},o.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),o.r=r=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(r,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(r,"__esModule",{value:!0})},o.nc=void 0;var a={};o.r(a),o.d(a,{Button:()=>E,Chevron:()=>U,ExpandablePanel:()=>F});var c=o(12),i=o(894),l=o.n(i),s=o(72),u=o.n(s),f=o(825),p=o.n(f),d=o(659),v=o.n(d),b=o(56),y=o.n(b),m=o(540),g=o.n(m),h=o(113),x=o.n(h),O=o(998),j={};j.styleTagTransform=x(),j.setAttributes=y(),j.insert=v().bind(null,"head"),j.domAPI=p(),j.insertStyleElement=g(),u()(O.A,j),O.A&&O.A.locals&&O.A.locals;var w=o(848);function S(r){return S="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(r){return typeof r}:function(r){return r&&"function"==typeof Symbol&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},S(r)}var P=["color","variant","size","className","disabled","type"];function A(r,e){var n=Object.keys(r);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(r);e&&(t=t.filter(function(e){return Object.getOwnPropertyDescriptor(r,e).enumerable})),n.push.apply(n,t)}return n}function k(r,e,n){return(e=function(r){var e=function(r){if("object"!=S(r)||!r)return r;var e=r[Symbol.toPrimitive];if(void 0!==e){var n=e.call(r,"string");if("object"!=S(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(r)}(r);return"symbol"==S(e)?e:e+""}(e))in r?Object.defineProperty(r,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):r[e]=n,r}var E=(0,c.forwardRef)(function(r,e){var n=r.color,t=void 0===n?"default":n,o=r.variant,a=void 0===o?"solid":o,c=r.size,i=void 0===c?"md":c,s=r.className,u=r.disabled,f=r.type,p=void 0===f?"button":f,d=function(r,e){if(null==r)return{};var n,t,o=function(r,e){if(null==r)return{};var n={};for(var t in r)if({}.hasOwnProperty.call(r,t)){if(-1!==e.indexOf(t))continue;n[t]=r[t]}return n}(r,e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(r);for(t=0;t<a.length;t++)n=a[t],-1===e.indexOf(n)&&{}.propertyIsEnumerable.call(r,n)&&(o[n]=r[n])}return o}(r,P),v=function(r,e,n,t){var o=["btn","btn-".concat(n),t];switch(r){case"solid":o.push("btn-".concat(e));break;case"outline":o.push("btn-outline-".concat(e));break;case"ghost":o.push("btn-ghost-".concat(e))}return l()(o)}(a,t,i,s);return(0,w.jsx)("button",function(r){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?A(Object(n),!0).forEach(function(e){k(r,e,n[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(r,Object.getOwnPropertyDescriptors(n)):A(Object(n)).forEach(function(e){Object.defineProperty(r,e,Object.getOwnPropertyDescriptor(n,e))})}return r}({ref:e,type:p,className:v,disabled:u},d))});E.displayName="Button";var T=o(525),N={};function I(r){return I="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(r){return typeof r}:function(r){return r&&"function"==typeof Symbol&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},I(r)}N.styleTagTransform=x(),N.setAttributes=y(),N.insert=v().bind(null,"head"),N.domAPI=p(),N.insertStyleElement=g(),u()(T.A,N),T.A&&T.A.locals&&T.A.locals;var C=["direction","open","size","strokeWidth","className","title","animated"];function M(r,e){var n=Object.keys(r);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(r);e&&(t=t.filter(function(e){return Object.getOwnPropertyDescriptor(r,e).enumerable})),n.push.apply(n,t)}return n}function D(r){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?M(Object(n),!0).forEach(function(e){z(r,e,n[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(r,Object.getOwnPropertyDescriptors(n)):M(Object(n)).forEach(function(e){Object.defineProperty(r,e,Object.getOwnPropertyDescriptor(n,e))})}return r}function z(r,e,n){return(e=function(r){var e=function(r){if("object"!=I(r)||!r)return r;var e=r[Symbol.toPrimitive];if(void 0!==e){var n=e.call(r,"string");if("object"!=I(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(r)}(r);return"symbol"==I(e)?e:e+""}(e))in r?Object.defineProperty(r,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):r[e]=n,r}function U(r){var e=r.direction,n=void 0===e?"down":e,t=r.open,o=r.size,a=void 0===o?16:o,c=r.strokeWidth,i=void 0===c?2:c,s=r.className,u=r.title,f=r.animated,p=void 0===f||f,d=function(r,e){if(null==r)return{};var n,t,o=function(r,e){if(null==r)return{};var n={};for(var t in r)if({}.hasOwnProperty.call(r,t)){if(-1!==e.indexOf(t))continue;n[t]=r[t]}return n}(r,e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(r);for(t=0;t<a.length;t++)n=a[t],-1===e.indexOf(n)&&{}.propertyIsEnumerable.call(r,n)&&(o[n]=r[n])}return o}(r,C),v={down:0,up:180,left:90,right:-90},b=void 0===t?v[n]:"down"===n?t?180:0:"right"===n?t?0:-90:v[n],y=0===b?"rotate-0":180===b?"rotate-180":90===b?"rotate-90":-90===b?"-rotate-90":"rotate-0";return(0,w.jsxs)("svg",D(D({xmlns:"http://www.w3.org/2000/svg",width:a,height:a,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:i,strokeLinecap:"round",strokeLinejoin:"round",className:l()("shrink-0",p&&"chevron-animated",y,s),"aria-hidden":!d["aria-label"]||void 0,role:d["aria-label"]?"img":void 0},d),{},{children:[u?(0,w.jsx)("title",{children:u}):null,(0,w.jsx)("path",{d:"M6 9l6 6 6-6"})]}))}var q=o(405),L={};function R(r){return R="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(r){return typeof r}:function(r){return r&&"function"==typeof Symbol&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},R(r)}function _(r,e){var n=Object.keys(r);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(r);e&&(t=t.filter(function(e){return Object.getOwnPropertyDescriptor(r,e).enumerable})),n.push.apply(n,t)}return n}function B(r){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?_(Object(n),!0).forEach(function(e){W(r,e,n[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(r,Object.getOwnPropertyDescriptors(n)):_(Object(n)).forEach(function(e){Object.defineProperty(r,e,Object.getOwnPropertyDescriptor(n,e))})}return r}function W(r,e,n){return(e=function(r){var e=function(r){if("object"!=R(r)||!r)return r;var e=r[Symbol.toPrimitive];if(void 0!==e){var n=e.call(r,"string");if("object"!=R(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(r)}(r);return"symbol"==R(e)?e:e+""}(e))in r?Object.defineProperty(r,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):r[e]=n,r}function $(r,e){(null==e||e>r.length)&&(e=r.length);for(var n=0,t=Array(e);n<e;n++)t[n]=r[n];return t}L.styleTagTransform=x(),L.setAttributes=y(),L.insert=v().bind(null,"head"),L.domAPI=p(),L.insertStyleElement=g(),u()(q.A,L),q.A&&q.A.locals&&q.A.locals;var F=function(r){var e,n,t=r.title,o=r.children,a=r.className,i=r.chevronProps,s=r.defaultOpen,u=void 0===s||s,f=(e=(0,c.useState)(u),n=2,function(r){if(Array.isArray(r))return r}(e)||function(r,e){var n=null==r?null:"undefined"!=typeof Symbol&&r[Symbol.iterator]||r["@@iterator"];if(null!=n){var t,o,a,c,i=[],l=!0,s=!1;try{if(a=(n=n.call(r)).next,0===e){if(Object(n)!==n)return;l=!1}else for(;!(l=(t=a.call(n)).done)&&(i.push(t.value),i.length!==e);l=!0);}catch(r){s=!0,o=r}finally{try{if(!l&&null!=n.return&&(c=n.return(),Object(c)!==c))return}finally{if(s)throw o}}return i}}(e,n)||function(r,e){if(r){if("string"==typeof r)return $(r,e);var n={}.toString.call(r).slice(8,-1);return"Object"===n&&r.constructor&&(n=r.constructor.name),"Map"===n||"Set"===n?Array.from(r):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?$(r,e):void 0}}(e,n)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),p=f[0],d=f[1];return(0,w.jsxs)("div",{className:l()("cpanel",a),children:[(0,w.jsxs)("div",{className:"cpanel-header",onClick:function(){return d(function(r){return!r})},"aria-expanded":p,children:[(0,w.jsx)("div",{className:"cpanel-header-title",children:t}),(0,w.jsx)("div",{className:"cpanel-chevron",children:(0,w.jsx)(U,B({direction:"right",open:p,className:"text-current cursor-pointer",size:24},i))})]}),(0,w.jsx)("div",{className:l()("cpanel-content",p&&"open"),children:o})]})};return a})());
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tsp-form",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "A unified Tailwind 4 variables compatible UI component library for my own projects.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.esm.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"dev": "webpack serve --mode development --env APP_MODE=example",
|
|
10
|
+
"build": "webpack --mode production --env APP_MODE=library",
|
|
11
|
+
"clean": "rm -rf dist",
|
|
12
|
+
"build:lib": "webpack --env APP_MODE=library",
|
|
13
|
+
"build:example": "webpack",
|
|
14
|
+
"start:example": "webpack serve",
|
|
15
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"react",
|
|
19
|
+
"component",
|
|
20
|
+
"ui",
|
|
21
|
+
"tailwind"
|
|
22
|
+
],
|
|
23
|
+
"author": "Tsupol",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"clsx": "^2.1.1",
|
|
27
|
+
"react": "^19.1.0",
|
|
28
|
+
"react-dom": "^19.1.0",
|
|
29
|
+
"react-hook-form": "^7.62.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@babel/core": "^7.28.3",
|
|
33
|
+
"@babel/preset-env": "^7.28.3",
|
|
34
|
+
"@babel/preset-react": "^7.27.1",
|
|
35
|
+
"@babel/preset-typescript": "^7.27.1",
|
|
36
|
+
"@types/react": "^19.1.12",
|
|
37
|
+
"@types/react-dom": "^19.1.9",
|
|
38
|
+
"babel-loader": "^10.0.0",
|
|
39
|
+
"css-loader": "^7.1.2",
|
|
40
|
+
"html-webpack-plugin": "^5.6.4",
|
|
41
|
+
"style-loader": "^4.0.0",
|
|
42
|
+
"typescript": "^5.9.2",
|
|
43
|
+
"webpack": "^5.101.3",
|
|
44
|
+
"webpack-cli": "^6.0.1",
|
|
45
|
+
"webpack-dev-server": "^5.2.2"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
import "../styles/button.css";
|
|
4
|
+
|
|
5
|
+
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
6
|
+
color?: string;
|
|
7
|
+
variant?: string;
|
|
8
|
+
size?: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function getClassName(variant: string, color: string, size: string, className?: string) {
|
|
13
|
+
const classes = ['btn', `btn-${size}`, className];
|
|
14
|
+
switch (variant) {
|
|
15
|
+
case 'solid':
|
|
16
|
+
classes.push(`btn-${color}`);
|
|
17
|
+
break;
|
|
18
|
+
case 'outline':
|
|
19
|
+
classes.push(`btn-outline-${color}`);
|
|
20
|
+
break;
|
|
21
|
+
case 'ghost':
|
|
22
|
+
classes.push(`btn-ghost-${color}`);
|
|
23
|
+
break;
|
|
24
|
+
default:
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
return clsx(classes);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
31
|
+
(
|
|
32
|
+
{
|
|
33
|
+
color = "default",
|
|
34
|
+
variant = "solid",
|
|
35
|
+
size = "md",
|
|
36
|
+
className,
|
|
37
|
+
disabled,
|
|
38
|
+
type = "button",
|
|
39
|
+
...props
|
|
40
|
+
},
|
|
41
|
+
ref
|
|
42
|
+
) => {
|
|
43
|
+
const classes = getClassName(variant, color, size, className);
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<button
|
|
47
|
+
ref={ref}
|
|
48
|
+
type={type}
|
|
49
|
+
className={classes}
|
|
50
|
+
disabled={disabled}
|
|
51
|
+
{...props}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
Button.displayName = "Button";
|
|
58
|
+
|
|
59
|
+
export default Button;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import '../styles/chevron.css';
|
|
4
|
+
|
|
5
|
+
type Direction = 'down' | 'up' | 'left' | 'right';
|
|
6
|
+
|
|
7
|
+
export type ChevronProps = {
|
|
8
|
+
direction?: Direction; // visual direction when "closed"
|
|
9
|
+
open?: boolean; // if provided, animates to an "expanded" angle
|
|
10
|
+
size?: number | string; // 16 | 20 | '1em' | '24px' ...
|
|
11
|
+
strokeWidth?: number; // 1 to 2.5 typically
|
|
12
|
+
className?: string;
|
|
13
|
+
title?: string;
|
|
14
|
+
'aria-label'?: string;
|
|
15
|
+
animated?: boolean; // enables CSS transition
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export function Chevron({
|
|
19
|
+
direction = 'down',
|
|
20
|
+
open,
|
|
21
|
+
size = 16,
|
|
22
|
+
strokeWidth = 2,
|
|
23
|
+
className,
|
|
24
|
+
title,
|
|
25
|
+
animated = true,
|
|
26
|
+
...aria
|
|
27
|
+
}: ChevronProps) {
|
|
28
|
+
// Base rotation angles for the "closed" state
|
|
29
|
+
const baseAngle: Record<Direction, number> = {
|
|
30
|
+
down: 0,
|
|
31
|
+
up: 180,
|
|
32
|
+
left: 90,
|
|
33
|
+
right: -90,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// If `open` is provided, rotate to a sensible expanded angle
|
|
37
|
+
const angle = (() => {
|
|
38
|
+
if (open === undefined) return baseAngle[direction];
|
|
39
|
+
if (direction === 'down') return open ? 180 : 0; // caret flips up when open
|
|
40
|
+
if (direction === 'right') return open ? 0 : -90; // caret points down when open
|
|
41
|
+
// For 'up' and 'left' keep base angle unless you want a custom behavior
|
|
42
|
+
return baseAngle[direction];
|
|
43
|
+
})();
|
|
44
|
+
|
|
45
|
+
// Map to Tailwind rotation classes we actually use
|
|
46
|
+
const angleClass =
|
|
47
|
+
angle === 0
|
|
48
|
+
? 'rotate-0'
|
|
49
|
+
: angle === 180
|
|
50
|
+
? 'rotate-180'
|
|
51
|
+
: angle === 90
|
|
52
|
+
? 'rotate-90'
|
|
53
|
+
: angle === -90
|
|
54
|
+
? '-rotate-90'
|
|
55
|
+
: 'rotate-0';
|
|
56
|
+
|
|
57
|
+
// Inline SVG chevron (stroke follows currentColor)
|
|
58
|
+
return (
|
|
59
|
+
<svg
|
|
60
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
61
|
+
width={size as number}
|
|
62
|
+
height={size as number}
|
|
63
|
+
viewBox="0 0 24 24"
|
|
64
|
+
fill="none"
|
|
65
|
+
stroke="currentColor"
|
|
66
|
+
strokeWidth={strokeWidth}
|
|
67
|
+
strokeLinecap="round"
|
|
68
|
+
strokeLinejoin="round"
|
|
69
|
+
className={clsx(
|
|
70
|
+
'shrink-0',
|
|
71
|
+
animated && 'chevron-animated',
|
|
72
|
+
angleClass,
|
|
73
|
+
className
|
|
74
|
+
)}
|
|
75
|
+
aria-hidden={aria['aria-label'] ? undefined : true}
|
|
76
|
+
role={aria['aria-label'] ? 'img' : undefined}
|
|
77
|
+
{...aria}
|
|
78
|
+
>
|
|
79
|
+
{title ? <title>{title}</title> : null}
|
|
80
|
+
{/* ChevronDown path */}
|
|
81
|
+
<path d="M6 9l6 6 6-6" />
|
|
82
|
+
</svg>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { Chevron } from './Chevron';
|
|
4
|
+
import '../styles/collapsible-panel.css';
|
|
5
|
+
|
|
6
|
+
export const ExpandablePanel = ({
|
|
7
|
+
title,
|
|
8
|
+
children,
|
|
9
|
+
className,
|
|
10
|
+
chevronProps,
|
|
11
|
+
defaultOpen = true,
|
|
12
|
+
}: {
|
|
13
|
+
title: string;
|
|
14
|
+
className?: string;
|
|
15
|
+
children: React.ReactNode;
|
|
16
|
+
chevronProps?: React.ComponentProps<typeof Chevron>;
|
|
17
|
+
defaultOpen?: boolean;
|
|
18
|
+
}) => {
|
|
19
|
+
const [open, setOpen] = useState(defaultOpen);
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div className={clsx('cpanel', className)}>
|
|
23
|
+
<div
|
|
24
|
+
className="cpanel-header"
|
|
25
|
+
onClick={() => setOpen((v) => !v)}
|
|
26
|
+
aria-expanded={open}
|
|
27
|
+
>
|
|
28
|
+
<div className="cpanel-header-title">{title}</div>
|
|
29
|
+
<div className="cpanel-chevron">
|
|
30
|
+
<Chevron direction="right" open={open} className="text-current cursor-pointer" size={24} {...chevronProps}/>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div className={clsx('cpanel-content', open && 'open')}>
|
|
35
|
+
{children}
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ContentPanel } from './components/ContentPanel';
|
|
3
|
+
import Button from '../components/Button';
|
|
4
|
+
|
|
5
|
+
export function ExampleButtons() {
|
|
6
|
+
return (
|
|
7
|
+
<div className="grid gap-4">
|
|
8
|
+
<ContentPanel title="CSS Buttons">
|
|
9
|
+
<div className="flex gap-2 border border-line bg-surface p-card">
|
|
10
|
+
<button className="btn">
|
|
11
|
+
Button
|
|
12
|
+
</button>
|
|
13
|
+
<button className="btn btn-primary">
|
|
14
|
+
Button Primary
|
|
15
|
+
</button>
|
|
16
|
+
<button className="btn btn-secondary">
|
|
17
|
+
Button Secondary
|
|
18
|
+
</button>
|
|
19
|
+
<button className="btn btn-secondary disabled">
|
|
20
|
+
Button Secondary
|
|
21
|
+
</button>
|
|
22
|
+
</div>
|
|
23
|
+
<div className="flex gap-2 border border-line bg-surface p-card">
|
|
24
|
+
<button className="btn btn-outline-default">
|
|
25
|
+
Button
|
|
26
|
+
</button>
|
|
27
|
+
<button className="btn btn-outline-primary">
|
|
28
|
+
Button Primary
|
|
29
|
+
</button>
|
|
30
|
+
<button className="btn btn-outline-secondary">
|
|
31
|
+
Outline Secondary
|
|
32
|
+
</button>
|
|
33
|
+
<button className="btn btn-outline-secondary disabled">
|
|
34
|
+
Outline Secondary
|
|
35
|
+
</button>
|
|
36
|
+
</div>
|
|
37
|
+
<div className="flex gap-2 border border-line bg-surface p-card">
|
|
38
|
+
<button className="btn btn-ghost-default">
|
|
39
|
+
Ghost
|
|
40
|
+
</button>
|
|
41
|
+
<button className="btn btn-ghost-primary">
|
|
42
|
+
Ghost Primary
|
|
43
|
+
</button>
|
|
44
|
+
<button className="btn btn-ghost-secondary">
|
|
45
|
+
Ghost Secondary
|
|
46
|
+
</button>
|
|
47
|
+
<button className="btn btn-ghost-secondary disabled">
|
|
48
|
+
Ghost Secondary
|
|
49
|
+
</button>
|
|
50
|
+
</div>
|
|
51
|
+
<div className="flex gap-2 border border-line bg-surface p-card">
|
|
52
|
+
<button className="btn btn-lg">
|
|
53
|
+
Large
|
|
54
|
+
</button>
|
|
55
|
+
<button className="btn btn-sm">
|
|
56
|
+
Small
|
|
57
|
+
</button>
|
|
58
|
+
<button className="btn btn-outline-default btn-lg">
|
|
59
|
+
Large
|
|
60
|
+
</button>
|
|
61
|
+
<div>
|
|
62
|
+
<button className="btn btn-outline-secondary btn-sm">
|
|
63
|
+
Small
|
|
64
|
+
</button>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</ContentPanel>
|
|
68
|
+
<ContentPanel title="React Buttons">
|
|
69
|
+
<div className="flex gap-2 border border-line bg-surface p-card">
|
|
70
|
+
<Button>
|
|
71
|
+
Button
|
|
72
|
+
</Button>
|
|
73
|
+
<Button color="primary">
|
|
74
|
+
Button Primary
|
|
75
|
+
</Button>
|
|
76
|
+
<Button color="secondary">
|
|
77
|
+
Button Secondary
|
|
78
|
+
</Button>
|
|
79
|
+
<Button color="secondary" disabled>
|
|
80
|
+
Button Secondary
|
|
81
|
+
</Button>
|
|
82
|
+
</div>
|
|
83
|
+
<div className="flex gap-2 border border-line bg-surface p-card">
|
|
84
|
+
<Button variant="outline">
|
|
85
|
+
Button
|
|
86
|
+
</Button>
|
|
87
|
+
<Button variant="outline" color="primary">
|
|
88
|
+
Button Primary
|
|
89
|
+
</Button>
|
|
90
|
+
<Button variant="outline" color="secondary">
|
|
91
|
+
Outline Secondary
|
|
92
|
+
</Button>
|
|
93
|
+
<Button variant="outline" color="secondary" disabled>
|
|
94
|
+
Outline Secondary
|
|
95
|
+
</Button>
|
|
96
|
+
</div>
|
|
97
|
+
<div className="flex gap-2 border border-line bg-surface p-card">
|
|
98
|
+
<Button variant="ghost">
|
|
99
|
+
Ghost
|
|
100
|
+
</Button>
|
|
101
|
+
<Button variant="ghost" color="primary">
|
|
102
|
+
Ghost Primary
|
|
103
|
+
</Button>
|
|
104
|
+
<Button variant="ghost" color="secondary">
|
|
105
|
+
Ghost Secondary
|
|
106
|
+
</Button>
|
|
107
|
+
<Button variant="ghost" color="secondary" disabled>
|
|
108
|
+
Ghost Secondary
|
|
109
|
+
</Button>
|
|
110
|
+
</div>
|
|
111
|
+
<div className="flex gap-2 border border-line bg-surface p-card">
|
|
112
|
+
<Button size="lg">
|
|
113
|
+
Large
|
|
114
|
+
</Button>
|
|
115
|
+
<Button size="sm">
|
|
116
|
+
Small
|
|
117
|
+
</Button>
|
|
118
|
+
<Button variant="outline" size="lg">
|
|
119
|
+
Large
|
|
120
|
+
</Button>
|
|
121
|
+
<div>
|
|
122
|
+
<Button variant="outline" color="secondary" size="sm">
|
|
123
|
+
Small
|
|
124
|
+
</Button>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
</ContentPanel>
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export const ContentPanel = ({ title, children }: { title: string; children: React.ReactNode}) => {
|
|
4
|
+
return (
|
|
5
|
+
<div className="content-panel">
|
|
6
|
+
<div className="content-panel-header-wrapper">
|
|
7
|
+
<span className="content-panel-header">{title}</span>
|
|
8
|
+
</div>
|
|
9
|
+
{children}
|
|
10
|
+
</div>
|
|
11
|
+
)
|
|
12
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
@import '../global.css';
|
|
2
|
+
@import './styles/components.css';
|
|
3
|
+
@import './styles/utils.css';
|
|
4
|
+
|
|
5
|
+
:root {
|
|
6
|
+
--color-danger: #ff0000;
|
|
7
|
+
--color-danger-contrast: #ffffff;
|
|
8
|
+
--spacing-main-sidebar: 10rem;
|
|
9
|
+
--spacing-mini-sidebar: 2.5rem;
|
|
10
|
+
--spacing-card: 1rem;
|
|
11
|
+
|
|
12
|
+
--color-fg: #cccccc;
|
|
13
|
+
--color-fg-contrast: #000000;
|
|
14
|
+
--color-bg: #0a0a0a;
|
|
15
|
+
--color-bg-contrast: #ffffff;
|
|
16
|
+
|
|
17
|
+
--color-line: #2a2a2a;
|
|
18
|
+
--color-link: #0070f3;
|
|
19
|
+
|
|
20
|
+
--color-surface: rgba(255, 255, 255, 0.025);
|
|
21
|
+
--color-surface-hover: rgba(255, 255, 255, 0.05);
|
|
22
|
+
--color-surface-shallow: rgba(255, 255, 255, 0.01);
|
|
23
|
+
--color-surface-elevated: rgba(255, 255, 255, 0.05);
|
|
24
|
+
|
|
25
|
+
--spacing-line: 1px;
|
|
26
|
+
|
|
27
|
+
--color-primary: #0070f3;
|
|
28
|
+
--color-primary-hover: #005bb5;
|
|
29
|
+
--color-primary-active: #004c9b;
|
|
30
|
+
--color-primary-contrast: #ffffff;
|
|
31
|
+
--color-primary-light: rgba(0, 112, 243, 0.1);
|
|
32
|
+
|
|
33
|
+
--color-secondary: #8200ff;
|
|
34
|
+
--color-secondary-hover: #6800cc;
|
|
35
|
+
--color-secondary-active: #5300a8;
|
|
36
|
+
--color-secondary-contrast: #ffffff;
|
|
37
|
+
|
|
38
|
+
--spacing-control-y: 0.625rem;
|
|
39
|
+
--spacing-control-x: 1rem;
|
|
40
|
+
--spacing-control-compact-y: 0.25rem;
|
|
41
|
+
--spacing-control-compact-x: 0.5rem;
|
|
42
|
+
--spacing-control-relaxed-y: 1rem;
|
|
43
|
+
--spacing-control-relaxed-x: 2rem;
|
|
44
|
+
--radius-control: .5rem;
|
|
45
|
+
--text-control: 1rem;
|
|
46
|
+
--text-control--letter-spacing: 0em;
|
|
47
|
+
--text-control--line-height: 1.5;
|
|
48
|
+
--text-control--font-weight: 400;
|
|
49
|
+
|
|
50
|
+
--space-scrollbar-track: .5rem;
|
|
51
|
+
--color-scrollbar-track: rgba(125, 125, 125, 0.1);
|
|
52
|
+
--color-scrollbar-thumb: rgba(125, 125, 125, 0.25);
|
|
53
|
+
--color-bg-control: transparent;
|
|
54
|
+
--color-label-control: #888888;
|
|
55
|
+
|
|
56
|
+
--space-title-x: 1rem;
|
|
57
|
+
--space-title-y: 1rem;
|
|
58
|
+
--text-title: 1.5rem;
|
|
59
|
+
--text-title--letter-spacing: -0.025em;
|
|
60
|
+
--text-title--line-height: 1.25;
|
|
61
|
+
--text-title--font-weight: 600;
|
|
62
|
+
|
|
63
|
+
--spacing-title-y: 1rem;
|
|
64
|
+
--spacing-title-x: 1rem;
|
|
65
|
+
--spacing-title-h: calc(var(--spacing-title-y) * 2 + var(--text-title) * var(--text-title--line-height));
|
|
66
|
+
|
|
67
|
+
--text-base: 1rem;
|
|
68
|
+
--text-base--letter-spacing: 0em;
|
|
69
|
+
--text-base--line-height: 1.5;
|
|
70
|
+
--text-base--font-weight: 400;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
html, body {
|
|
74
|
+
background: var(--color-bg);
|
|
75
|
+
color: var(--color-fg);
|
|
76
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
77
|
+
font-size: var(--text-base);
|
|
78
|
+
line-height: var(--text-base--line-height);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.page-content {
|
|
82
|
+
padding: 1rem 2rem;
|
|
83
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Button Component Example</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="root"></div>
|
|
10
|
+
<!-- Webpack will inject the bundle.js here -->
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { createRoot } from 'react-dom/client';
|
|
3
|
+
import { ExpandablePanel } from '../components/ExpandablePanel';
|
|
4
|
+
import { ExampleButtons } from './ExampleButtons';
|
|
5
|
+
import './example.css';
|
|
6
|
+
|
|
7
|
+
const App = () => {
|
|
8
|
+
return (
|
|
9
|
+
<div>
|
|
10
|
+
<ExpandablePanel title="Buttons">
|
|
11
|
+
<ExampleButtons />
|
|
12
|
+
</ExpandablePanel>
|
|
13
|
+
</div>
|
|
14
|
+
);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const container = document.getElementById('root');
|
|
18
|
+
if (container) {
|
|
19
|
+
const root = createRoot(container);
|
|
20
|
+
root.render(<App />);
|
|
21
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
.content-panel {
|
|
2
|
+
padding: 1rem;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.content-panel-header-wrapper {
|
|
6
|
+
padding-left: .5rem;
|
|
7
|
+
padding-bottom: .5rem;
|
|
8
|
+
border-left: .5rem solid var(--color-primary);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.content-panel-header {
|
|
12
|
+
font-size: 1.25rem;
|
|
13
|
+
font-weight: 600;
|
|
14
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
.flex {
|
|
2
|
+
display: flex;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.gap-2 {
|
|
6
|
+
gap: 0.5rem;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.border {
|
|
10
|
+
border: 1px solid var(--color-line);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.border-line {
|
|
14
|
+
border-color: var(--color-line);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.bg-surface {
|
|
18
|
+
background-color: var(--color-surface);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.p-card {
|
|
22
|
+
padding: 1rem;
|
|
23
|
+
}
|
package/src/global.css
ADDED
package/src/index.ts
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
.btn {
|
|
2
|
+
--color-text: var(--color-fg);
|
|
3
|
+
--color-bg: var(--color-surface);
|
|
4
|
+
--color-border: var(--color-surface);
|
|
5
|
+
--color-bg-hover: var(--color-fg);
|
|
6
|
+
--color-border-hover: var(--color-fg);
|
|
7
|
+
--color-text-hover: var(--color-fg-contrast);
|
|
8
|
+
padding: var(--spacing-control-y) var(--spacing-control-x);
|
|
9
|
+
border-radius: var(--radius-control);
|
|
10
|
+
border: 1px solid var(--color-border);
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
background: var(--color-bg);
|
|
13
|
+
color: var(--color-text);
|
|
14
|
+
transition: all 0.2s ease-in-out;
|
|
15
|
+
display: inline-flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
justify-content: center;
|
|
18
|
+
font-weight: 600;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.btn:hover {
|
|
22
|
+
background: var(--color-bg-hover);
|
|
23
|
+
border-color: var(--color-border-hover);
|
|
24
|
+
color: var(--color-text-hover);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.btn.disabled {
|
|
28
|
+
opacity: 0.5;
|
|
29
|
+
pointer-events: none;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.btn-sm {
|
|
33
|
+
padding: var(--spacing-control-compact-y) var(--spacing-control-compact-x);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.btn-lg {
|
|
37
|
+
padding: var(--spacing-control-relaxed-y) var(--spacing-control-relaxed-x);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.btn-primary {
|
|
41
|
+
--color-text: var(--color-primary-contrast);
|
|
42
|
+
--color-bg: var(--color-primary);
|
|
43
|
+
--color-border: var(--color-primary);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.btn-secondary {
|
|
47
|
+
--color-text: var(--color-secondary-contrast);
|
|
48
|
+
--color-bg: var(--color-secondary);
|
|
49
|
+
--color-border: var(--color-secondary);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.btn-danger {
|
|
53
|
+
--color-text: var(--color-danger-contrast);
|
|
54
|
+
--color-bg: var(--color-danger);
|
|
55
|
+
--color-border: var(--color-danger);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.btn-outline-default {
|
|
59
|
+
--color-text: var(--color-fg);
|
|
60
|
+
--color-bg: transparent;
|
|
61
|
+
--color-border: var(--color-line);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.btn-outline-primary {
|
|
65
|
+
--color-text: var(--color-primary);
|
|
66
|
+
--color-border: var(--color-primary);
|
|
67
|
+
--color-text-hover: var(--color-primary-contrast);
|
|
68
|
+
--color-bg-hover: var(--color-primary);
|
|
69
|
+
--color-border-hover: var(--color-primary);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.btn-outline-secondary {
|
|
73
|
+
--color-text: var(--color-secondary);
|
|
74
|
+
--color-border: var(--color-secondary);
|
|
75
|
+
--color-text-hover: var(--color-secondary-contrast);
|
|
76
|
+
--color-bg-hover: var(--color-secondary);
|
|
77
|
+
--color-border-hover: var(--color-secondary);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.btn-outline-danger {
|
|
81
|
+
--color-text: var(--color-danger);
|
|
82
|
+
--color-border: var(--color-danger);
|
|
83
|
+
--color-text-hover: var(--color-danger-contrast);
|
|
84
|
+
--color-bg-hover: var(--color-danger);
|
|
85
|
+
--color-border-hover: var(--color-danger);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.btn-ghost-default {
|
|
89
|
+
--color-text: var(--color-fg);
|
|
90
|
+
--color-bg: transparent;
|
|
91
|
+
--color-border: transparent;
|
|
92
|
+
--color-text-hover: var(--color-fg);
|
|
93
|
+
--color-bg-hover: var(--color-surface);
|
|
94
|
+
--color-border-hover: var(--color-surface);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.btn-ghost-primary {
|
|
98
|
+
--color-text: var(--color-primary);
|
|
99
|
+
--color-bg: transparent;
|
|
100
|
+
--color-border: transparent;
|
|
101
|
+
--color-text-hover: var(--color-fg);
|
|
102
|
+
--color-bg-hover: var(--color-surface);
|
|
103
|
+
--color-border-hover: var(--color-surface);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.btn-ghost-secondary {
|
|
107
|
+
--color-text: var(--color-secondary);
|
|
108
|
+
--color-bg: transparent;
|
|
109
|
+
--color-border: transparent;
|
|
110
|
+
--color-text-hover: var(--color-fg);
|
|
111
|
+
--color-bg-hover: var(--color-surface);
|
|
112
|
+
--color-border-hover: var(--color-surface);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.btn-ghost-danger {
|
|
116
|
+
--color-text: var(--color-danger);
|
|
117
|
+
--color-bg: transparent;
|
|
118
|
+
--color-border: transparent;
|
|
119
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.rotate-0 {
|
|
2
|
+
transform: rotate(0deg);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.rotate-90 {
|
|
6
|
+
transform: rotate(90deg);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.rotate-180 {
|
|
10
|
+
transform: rotate(180deg);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.-rotate-90 {
|
|
14
|
+
transform: rotate(-90deg);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.chevron-animated {
|
|
18
|
+
transition: transform 200ms ease-out;
|
|
19
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
.cpanel {
|
|
2
|
+
border: 1px solid var(--color-line);
|
|
3
|
+
border-radius: var(--radius-control);
|
|
4
|
+
overflow: hidden;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.cpanel-header {
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: space-between;
|
|
11
|
+
text-align: left;
|
|
12
|
+
border-bottom: 1px solid var(--color-line);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.cpanel-header-title {
|
|
16
|
+
padding: var(--spacing-title-y) var(--spacing-title-x);
|
|
17
|
+
letter-spacing: var(--text-title--letter-spacing);
|
|
18
|
+
font-size: var(--text-title);
|
|
19
|
+
line-height: var(--text-title--line-height);
|
|
20
|
+
font-weight: var(--text-title--font-weight);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.cpanel-header:focus {
|
|
24
|
+
outline: none;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.cpanel-header:focus-visible {
|
|
28
|
+
box-shadow: 0 0 0 1px var(--color-primary);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.cpanel-chevron {
|
|
32
|
+
flex-shrink: 0;
|
|
33
|
+
display: flex;
|
|
34
|
+
justify-content: center;
|
|
35
|
+
align-items: center;
|
|
36
|
+
width: var(--spacing-title-h);
|
|
37
|
+
height: var(--spacing-title-h);
|
|
38
|
+
border-left: var(--spacing-line) solid var(--color-line);
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.cpanel-content.open {
|
|
43
|
+
display: block;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.cpanel-content {
|
|
47
|
+
display: none;
|
|
48
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
@layer utilities {
|
|
2
|
+
.form-control {
|
|
3
|
+
border: 1px solid var(--color-line, #d1d5db);
|
|
4
|
+
border-radius: var(--radius-control, 0.375rem);
|
|
5
|
+
background-color: var(--color-bg-control, #ffffff);
|
|
6
|
+
padding: var(--spacing-control-y, 0.5rem) var(--spacing-control-y, 0.75rem);
|
|
7
|
+
transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
|
|
8
|
+
font-size: var(--text-control, 0.875rem);
|
|
9
|
+
font-weight: var(--text-control--font-weight, 400);
|
|
10
|
+
letter-spacing: var(--text-control--letter-spacing, 0em);
|
|
11
|
+
line-height: var(--text-control--line-height, 1.25);
|
|
12
|
+
min-height: calc(
|
|
13
|
+
var(--text-control--line-height) * var(--text-control, 0.875rem) +
|
|
14
|
+
2 * var(--spacing-control-y) +
|
|
15
|
+
2 * 1px /* Assuming 1px border*/
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.form-error-border .form-control, /* for Select */
|
|
21
|
+
.form-error-border {
|
|
22
|
+
border-color: var(--color-danger);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.form-control:focus-within {
|
|
26
|
+
border-color: var(--color-primary); /* Focus border color */
|
|
27
|
+
box-shadow: none;
|
|
28
|
+
outline: none;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.form-control:disabled {
|
|
32
|
+
opacity: 0.5;
|
|
33
|
+
cursor: not-allowed;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.form-label {
|
|
37
|
+
font-size: 0.875rem;
|
|
38
|
+
font-weight: 600;
|
|
39
|
+
color: var(--color-label-control);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.form-error {
|
|
43
|
+
color: var(--color-danger);
|
|
44
|
+
font-size: 0.75rem;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2019",
|
|
4
|
+
"module": "esnext",
|
|
5
|
+
"jsx": "react-jsx",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"forceConsistentCasingInFileNames": true,
|
|
10
|
+
"moduleResolution": "node",
|
|
11
|
+
"declaration": true,
|
|
12
|
+
"outDir": "./dist",
|
|
13
|
+
"baseUrl": "./",
|
|
14
|
+
"lib": ["dom", "dom.iterable", "esnext"]
|
|
15
|
+
},
|
|
16
|
+
"include": ["src"],
|
|
17
|
+
"exclude": ["node_modules", "dist", "src/example"] // Added: Exclude src/example
|
|
18
|
+
|
|
19
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
|
3
|
+
|
|
4
|
+
module.exports = (env) => {
|
|
5
|
+
const isLibraryBuild = env.APP_MODE === 'library';
|
|
6
|
+
|
|
7
|
+
const commonConfig = {
|
|
8
|
+
resolve: {
|
|
9
|
+
extensions: ['.ts', '.tsx', '.js', '.jsx'],
|
|
10
|
+
},
|
|
11
|
+
module: {
|
|
12
|
+
rules: [
|
|
13
|
+
{
|
|
14
|
+
test: /\.(ts|tsx|js|jsx)$/,
|
|
15
|
+
exclude: /node_modules/,
|
|
16
|
+
use: {
|
|
17
|
+
loader: 'babel-loader',
|
|
18
|
+
options: {
|
|
19
|
+
cacheDirectory: true,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
// Add this rule for CSS files
|
|
24
|
+
{
|
|
25
|
+
test: /\.css$/,
|
|
26
|
+
use: ['style-loader', 'css-loader'],
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
if (isLibraryBuild) {
|
|
33
|
+
return {
|
|
34
|
+
...commonConfig,
|
|
35
|
+
entry: './src/index.ts', // Entry point for the component library
|
|
36
|
+
output: {
|
|
37
|
+
path: path.resolve(__dirname, 'dist'),
|
|
38
|
+
filename: 'index.js',
|
|
39
|
+
library: {
|
|
40
|
+
name: 'MyUIComponents',
|
|
41
|
+
type: 'umd', // Universal Module Definition (CJS, AMD, global)
|
|
42
|
+
},
|
|
43
|
+
globalObject: 'this', // For UMD to work correctly in different environments
|
|
44
|
+
clean: true, // Clean the dist folder before each build
|
|
45
|
+
libraryTarget: 'umd', // Legacy, prefer 'library.type'
|
|
46
|
+
umdNamedDefine: true, // Give a name to the AMD module
|
|
47
|
+
auxiliaryComment: 'Button Component Library',
|
|
48
|
+
},
|
|
49
|
+
externals: {
|
|
50
|
+
// Don't bundle React and ReactDOM, expect them to be provided by the consumer
|
|
51
|
+
react: {
|
|
52
|
+
commonjs: 'react',
|
|
53
|
+
commonjs2: 'react',
|
|
54
|
+
amd: 'react',
|
|
55
|
+
root: 'React',
|
|
56
|
+
},
|
|
57
|
+
'react-dom': {
|
|
58
|
+
commonjs: 'react-dom',
|
|
59
|
+
commonjs2: 'react-dom',
|
|
60
|
+
amd: 'react-dom',
|
|
61
|
+
root: 'ReactDOM',
|
|
62
|
+
},
|
|
63
|
+
clsx: {
|
|
64
|
+
commonjs: 'clsx',
|
|
65
|
+
commonjs2: 'clsx',
|
|
66
|
+
amd: 'clsx',
|
|
67
|
+
root: 'clsx',
|
|
68
|
+
},
|
|
69
|
+
'react-hook-form': {
|
|
70
|
+
commonjs: 'react-hook-form',
|
|
71
|
+
commonjs2: 'react-hook-form',
|
|
72
|
+
amd: 'react-hook-form',
|
|
73
|
+
root: 'ReactHookForm',
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
},
|
|
77
|
+
optimization: {
|
|
78
|
+
minimize: true,
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
} else {
|
|
82
|
+
// Development server for the example app
|
|
83
|
+
return {
|
|
84
|
+
...commonConfig,
|
|
85
|
+
entry: './src/example/index.tsx', // Changed: Entry point for the example app
|
|
86
|
+
output: {
|
|
87
|
+
path: path.resolve(__dirname, 'dist'),
|
|
88
|
+
filename: 'bundle.js',
|
|
89
|
+
},
|
|
90
|
+
plugins: [
|
|
91
|
+
new HtmlWebpackPlugin({
|
|
92
|
+
template: path.resolve(__dirname, 'src/example/index.html'), // Changed: Path to your HTML template
|
|
93
|
+
}),
|
|
94
|
+
],
|
|
95
|
+
devServer: {
|
|
96
|
+
static: {
|
|
97
|
+
directory: path.join(__dirname, 'dist'), // The static directory should point to where webpack-dev-server serves files
|
|
98
|
+
},
|
|
99
|
+
compress: true,
|
|
100
|
+
port: 3000,
|
|
101
|
+
open: true,
|
|
102
|
+
hot: true,
|
|
103
|
+
},
|
|
104
|
+
devtool: 'eval-source-map',
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
};
|