diff --git a/src/index.js b/src/index.js index 04a3992..3a23ad3 100644 --- a/src/index.js +++ b/src/index.js @@ -9,10 +9,204 @@ function resolveColor(color, opacityVariableName) { return color.replace('', `var(${opacityVariableName}, 1)`) } +function rulesValueBuilder(theme) { + return { + baseAppearance: theme('forms.baseAppearance', 'none'), + basebackgroundColor: theme('forms.basebackgroundColor', colors.gray[500]), + baseBorderColor: theme('forms.baseBorderColor', colors.gray[500]), + baseBorderWith: theme('forms.baseBorderWith', borderWidth['DEFAULT']), + baseBorderRadius: theme('forms.baseBorderRadius', borderRadius['DEFAULT']), + baseTextColor: theme('forms.baseTextColor', colors.gray[500]), + basePaddingTop: theme('forms.basePaddingTop', spacing[2]), + basePaddingRight: theme('forms.basePaddingRight', spacing[3]), + basePaddingBottom: theme('forms.basePaddingBottom', spacing[2]), + basePaddingLeft: theme('forms.basePaddingLeft', spacing[3]), + baseFontSize: theme('forms.baseFontSize', baseFontSize), + baseLineHeight: theme('forms.baseLineHeight', baseLineHeight), + baseTwShadow: theme('forms.baseTwShadow', `0 0 ${colors.black}`), + baseFocusOutline: theme('forms.baseFocusOutline', '2px solid transparent'), + baseFocusOutlineOffset: theme('forms.baseFocusOutlineOffset', '2'), + baseFocusTwRingInset: theme('forms.baseFocusTwRingInset', 'var(--tw-empty,/*!*/ /*!*/)'), + baseFocusTwRingOffsetWidth: theme('forms.baseFocusTwRingOffsetWidth', '0'), + baseFocusTwRingOffsetColor: theme('forms.baseFocusTwRingOffsetColor', colors.white), + baseFocusTwRingColor: theme('forms.baseFocusTwRingColor', colors.blue[600]), + baseFocusTwRingOffsetShadow: theme( + 'forms.baseFocusTwRingOffsetShadow', + `var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)` + ), + baseFocusTwRingShadow: theme( + 'forms.baseFocusTwRingShadow', + `var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)` + ), + baseFocusBoxShadow: theme( + 'forms.baseFocusBoxShadow', + `var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)` + ), + baseFocusBorderColor: theme('forms.baseFocusBorderColor', colors.blue[600]), + basePlaceholderTextColor: theme('forms.basePlaceholderTextColor', colors.gray[500]), + basePlaceholderOpacity: theme('forms.basePlaceholderOpacity', '1'), + webkitDatetimePadding: theme('forms.webkitDatetimePadding', '0'), + webkitDatetimeMinHeight: theme('forms.webkitDatetimeMinHeight', '1.5em'), + webkitDatetimeTextAlign: theme('forms.webkitDatetimeTextAlign', 'inherit'), + webkitDatetimeDisplay: theme('forms.webkitDatetimeDisplay', 'inline-flex'), + webkitDatetimePaddingTop: theme('forms.webkitDatetimePaddingTop', 0), + webkitDatetimePaddingBottom: theme('forms.webkitDatetimePaddingBottom', 0), + selectBackgroundColor: theme('forms.selectBackgroundColor', colors.gray[500]), + selectBackgroundImage: theme( + 'forms.selectBackgroundImage', + `url("${svgToDataUri( + `` + )}")` + ), + selectBackgroundPosition: theme('forms.selectBackgroundPosition', `right ${spacing[2]} center`), + selectBackgroundRepeat: theme('forms.selectBackgroundRepeat', 'no-repeat'), + selectBackgroundSize: theme('forms.selectBackgroundSize', `1.5em 1.5em`), + selectPaddingRight: theme('forms.selectPaddingRight', spacing[10]), + selectPrintColorAdjust: theme('forms.selectPrintColorAdjust', 'exact'), + selectMultipleBackgroundImage: theme('forms.selectMultipleBackgroundImage', 'initial'), + selectMultipleBackgroundPosition: theme('forms.selectMultipleBackgroundPosition', 'initial'), + selectMultipleBackgroundRepeat: theme('forms.selectMultipleBackgroundRepeat', 'unset'), + selectMultipleBackgroundSize: theme('forms.selectMultipleBackgroundSize', 'initial'), + selectMultiplePaddingRight: theme('forms.selectMultiplePaddingRight', spacing[3]), + selectMultiplePrintColorAdjust: theme('forms.selectMultiplePrintColorAdjust', 'unset'), + checkboxAppearance: theme('forms.checkboxAppearance', 'none'), + checkboxPadding: theme('forms.checkboxPadding', '0'), + checkboxPrintColorAdjust: theme('forms.checkboxPrintColorAdjust', colors.blue[600]), + checkboxDisplay: theme('forms.checkboxDisplay', 'inline-block'), + checkboxVerticalAlign: theme('forms.checkboxVerticalAlign', 'middle'), + checkboxBackgroundOrigin: theme('forms.checkboxBackgroundOrigin', 'border-box'), + checkboxUserSelect: theme('forms.checkboxUserSelect', 'none'), + checkboxFlexShrink: theme('forms.checkboxFlexShrink', '0'), + checkboxHeight: theme('forms.checkboxHeight', spacing[4]), + checkboxWidth: theme('forms.checkboxWidth', spacing[4]), + checkboxColor: theme('forms.checkboxColor', colors.blue[600]), + checkboxBackgroundColor: theme('forms.checkboxBackgroundColor', colors.white), + checkboxBorderColor: theme('forms.checkboxBorderColor', colors.gray[500]), + checkboxBorderWidth: theme('forms.checkboxBorderWidth', borderWidth['DEFAULT']), + checkboxTWShadow: theme('forms.checkboxTWShadow', `0 0 ${colors.black}`), + checkboxBorderRadius: theme('forms.checkboxBorderRadius', borderRadius['none']), + radioBorderRadius: theme('forms.radioBorderRadius', '100%'), + + checkboxFocusOutline: theme('forms.checkboxFocusOutline', '2px solid transparent'), + checkboxFocusOutlineOffset: theme('forms.checkboxFocusOutlineOffset', '2px'), + checkboxFocusTwRingInset: theme( + 'forms.checkboxFocusTwRingInset', + 'var(--tw-empty,/*!*/ /*!*/)' + ), + checkboxFocusTwRingOffsetWidth: theme('forms.checkboxFocusTwRingOffsetWidth', '2px'), + checkboxFocusTwRingOffsetColor: theme('forms.checkboxFocusTwRingOffsetColor', '#fff'), + checkboxFocusTwRingColor: theme('forms.checkboxFocusTwRingColor', colors.blue[600]), + checkboxFocusTwRingOffsetShadow: theme( + 'forms.checkboxTwRingOffsetShadow', + `var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)` + ), + checkboxFocusTwRingShadow: theme( + 'forms.checkboxTwRingShadow', + `var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)` + ), + checkboxFocusBoxShadow: theme( + 'forms.checkboxBoxShadow', + `var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)` + ), + + checkboxBackgroundSize: theme('forms.checkboxBackgroundSize', `100% 100%`), + checkboxBackgroundPosition: theme('forms.checkboxBackgroundPosition', `center`), + checkboxBackgroundRepeat: theme('forms.checkboxBackgroundRepeat', `no-repeat`), + checkboxBackgroundFillColor: theme('forms.checkboxBackgroundFillColor', colors.white), + checkboxBackgroundImage: theme( + 'forms.checkboxBackgroundImage', + `url("${svgToDataUri( + `` + )}")` + ), + checkboxCheckedBackgroundFillColor: theme( + 'forms.checkboxCheckedBackgroundFillColor', + colors.white + ), + checkboxCheckedBackgroundColor: theme('forms.checkboxCheckedBackgroundColor', `currentColor`), + checkboxCheckedBackgroundImage: theme( + 'forms.checkboxCheckedBackgroundImage', + `url("${svgToDataUri( + `` + )}")` + ), + radioCheckedBackgroundFillColor: theme('forms.radioCheckedBackgroundFillColor', colors.white), + + radioCheckedBackgroundImage: theme( + 'forms.radioCheckedBackgroundImage', + `url("${svgToDataUri( + `` + )}")` + ), + + checkboxCheckedHoverBorderColor: theme('forms.checkboxCheckedHoverBorderColor', 'transparent'), + checkboxCheckedHoverBackgroundColor: theme( + 'forms.checkboxCheckedHoverBackgroundColor', + 'currentColor' + ), + + checkboxIndeterminateBorderColor: theme( + 'forms.checkboxIndeterminateBorderColor', + `transparent` + ), + checkboxIndeterminateBackgroundColor: theme( + 'forms.checkboxIndeterminateBackgroundColor', + `currentColor` + ), + checkboxIndeterminateBackgroundSize: theme( + 'forms.checkboxIndeterminateBackgroundSize', + `100% 100%` + ), + checkboxIndeterminateBackgroundPosition: theme( + 'forms.checkboxIndeterminateBackgroundPosition', + `center` + ), + checkboxIndeterminateBackgroundRepeat: theme( + 'forms.checkboxIndeterminateBackgroundRepeat', + `no-repeat` + ), + + checkboxIndeterminateHoverBorderColor: theme( + 'forms.checkboxIndeterminateHoverBorderColor', + 'transparent' + ), + checkboxIndeterminateHoverBackgroundColor: theme( + 'forms.checkboxIndeterminateHoverBackgroundColor', + 'currentColor' + ), + + fileBackground: theme('forms.fileBackground', 'unset'), + fileBorderColor: theme('forms.fileBorderColor', 'inherit'), + fileBorderWidth: theme('forms.fileBorderWidth', '0'), + fileBorderRadius: theme('forms.fileBorderRadius', '0'), + filepadding: theme('forms.filepadding', '0'), + fileFontSize: theme('forms.fileFontSize', 'unset'), + fileLineHeight: theme('forms.fileLineHeight', 'inherit'), + fileFocusOutline: theme('forms.fileFocusOutline', [ + `1px solid ButtonText`, + `1px auto -webkit-focus-ring-color`, + ]), + } +} + const forms = plugin.withOptions(function (options = { strategy: undefined }) { return function ({ addBase, addComponents, theme }) { const strategy = options.strategy === undefined ? ['base', 'class'] : [options.strategy] + const r = rulesValueBuilder(theme) + const rules = [ { base: [ @@ -36,37 +230,32 @@ const forms = plugin.withOptions(function (options = { strategy: undefined }) { class: ['.form-input', '.form-textarea', '.form-select', '.form-multiselect'], styles: { appearance: 'none', - 'background-color': '#fff', - 'border-color': resolveColor( - theme('colors.gray.500', colors.gray[500]), - '--tw-border-opacity' - ), - 'border-width': borderWidth['DEFAULT'], - 'border-radius': borderRadius.none, - 'padding-top': spacing[2], - 'padding-right': spacing[3], - 'padding-bottom': spacing[2], - 'padding-left': spacing[3], - 'font-size': baseFontSize, - 'line-height': baseLineHeight, - '--tw-shadow': '0 0 #0000', + 'background-color': r.baseAppearance, + 'border-color': resolveColor(r.baseBorderColor, '--tw-border-opacity'), + 'border-width': r.baseBorderWith, + 'border-radius': r.baseBorderRadius, + color: resolveColor(r.baseTextColor, '--tw-border-opacity'), + 'padding-top': r.basePaddingTop, + 'padding-right': r.basePaddingRight, + 'padding-bottom': r.basePaddingBottom, + 'padding-left': r.basePaddingLeft, + 'font-size': r.baseFontSize, + 'line-height': r.baseLineHeight, + '--tw-shadow': r.baseTwShadow, '&:focus': { - outline: '2px solid transparent', - 'outline-offset': '2px', - '--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-ring-offset-width': '0px', - '--tw-ring-offset-color': '#fff', - '--tw-ring-color': resolveColor( - theme('colors.blue.600', colors.blue[600]), + outline: r.baseFocusOutline, + 'outline-offset': r.baseFocusOutlineOffset, + '--tw-ring-inset': r.baseFocusTwRingInset, + '--tw-ring-offset-width': r.baseFocusTwRingOffsetWidth, + '--tw-ring-offset-color': resolveColor( + r.baseFocusTwRingOffsetColor, '--tw-ring-opacity' ), - '--tw-ring-offset-shadow': `var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)`, - '--tw-ring-shadow': `var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)`, - 'box-shadow': `var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)`, - 'border-color': resolveColor( - theme('colors.blue.600', colors.blue[600]), - '--tw-border-opacity' - ), + '--tw-ring-color': resolveColor(r.baseFocusTwRingColor, '--tw-ring-opacity'), + '--tw-ring-offset-shadow': r.baseFocusTwRingOffsetShadow, + '--tw-ring-shadow': r.baseFocusTwRingShadow, + 'box-shadow': r.baseFocusBoxShadow, + 'border-color': resolveColor(r.baseFocusBorderColor, '--tw-border-opacity'), }, }, }, @@ -74,15 +263,15 @@ const forms = plugin.withOptions(function (options = { strategy: undefined }) { base: ['input::placeholder', 'textarea::placeholder'], class: ['.form-input::placeholder', '.form-textarea::placeholder'], styles: { - color: resolveColor(theme('colors.gray.500', colors.gray[500]), '--tw-text-opacity'), - opacity: '1', + color: resolveColor(r.basePlaceholderTextColor, '--tw-text-opacity'), + opacity: r.basePlaceholderOpacity, }, }, { base: ['::-webkit-datetime-edit-fields-wrapper'], class: ['.form-input::-webkit-datetime-edit-fields-wrapper'], styles: { - padding: '0', + padding: r.webkitDatetimePadding, }, }, { @@ -92,7 +281,7 @@ const forms = plugin.withOptions(function (options = { strategy: undefined }) { base: ['::-webkit-date-and-time-value'], class: ['.form-input::-webkit-date-and-time-value'], styles: { - 'min-height': '1.5em', + 'min-height': r.webkitDatetimeMinHeight, }, }, { @@ -103,7 +292,7 @@ const forms = plugin.withOptions(function (options = { strategy: undefined }) { base: ['::-webkit-date-and-time-value'], class: ['.form-input::-webkit-date-and-time-value'], styles: { - 'text-align': 'inherit', + 'text-align': r.webkitDatetimeTextAlign, }, }, { @@ -114,7 +303,7 @@ const forms = plugin.withOptions(function (options = { strategy: undefined }) { base: ['::-webkit-datetime-edit'], class: ['.form-input::-webkit-datetime-edit'], styles: { - display: 'inline-flex', + display: r.webkitDatetimeDisplay, }, }, { @@ -144,122 +333,107 @@ const forms = plugin.withOptions(function (options = { strategy: undefined }) { '.form-input::-webkit-datetime-edit-meridiem-field', ], styles: { - 'padding-top': 0, - 'padding-bottom': 0, + 'padding-top': r.webkitDatetimePaddingTop, + 'padding-bottom': r.webkitDatetimePaddingBottom, }, }, { base: ['select'], class: ['.form-select'], styles: { - 'background-image': `url("${svgToDataUri( - `` - )}")`, - 'background-position': `right ${spacing[2]} center`, - 'background-repeat': `no-repeat`, - 'background-size': `1.5em 1.5em`, - 'padding-right': spacing[10], - 'print-color-adjust': `exact`, + 'background-image': r.selectBackgroundImage, + 'background-position': r.selectBackgroundPosition, + 'background-repeat': r.selectBackgroundRepeat, + 'background-size': r.selectBackgroundSize, + 'padding-right': r.selectPaddingRight, + 'print-color-adjust': r.selectPrintColorAdjust, }, }, { base: ['[multiple]', '[size]:where(select:not([size="1"]))'], class: ['.form-select:where([size]:not([size="1"]))'], styles: { - 'background-image': 'initial', - 'background-position': 'initial', - 'background-repeat': 'unset', - 'background-size': 'initial', - 'padding-right': spacing[3], - 'print-color-adjust': 'unset', + 'background-image': r.selectMultipleBackgroundImage, + 'background-position': r.selectMultipleBackgroundPosition, + 'background-repeat': r.selectMultipleBackgroundRepeat, + 'background-size': r.selectMultipleBackgroundSize, + 'padding-right': r.selectMultiplePaddingRight, + 'print-color-adjust': r.selectMultiplePrintColorAdjust, }, }, { base: [`[type='checkbox']`, `[type='radio']`], class: ['.form-checkbox', '.form-radio'], styles: { - appearance: 'none', - padding: '0', - 'print-color-adjust': 'exact', - display: 'inline-block', - 'vertical-align': 'middle', - 'background-origin': 'border-box', - 'user-select': 'none', - 'flex-shrink': '0', - height: spacing[4], - width: spacing[4], - color: resolveColor(theme('colors.blue.600', colors.blue[600]), '--tw-text-opacity'), - 'background-color': '#fff', - 'border-color': resolveColor( - theme('colors.gray.500', colors.gray[500]), - '--tw-border-opacity' - ), - 'border-width': borderWidth['DEFAULT'], - '--tw-shadow': '0 0 #0000', + appearance: r.checkboxAppearance, + padding: r.checkboxPadding, + 'print-color-adjust': r.checkboxPrintColorAdjust, + display: r.checkboxDisplay, + 'vertical-align': r.checkboxVerticalAlign, + 'background-origin': r.checkboxBackgroundOrigin, + 'user-select': r.checkboxUserSelect, + 'flex-shrink': r.checkboxFlexShrink, + height: r.checkboxHeight, + width: r.checkboxWidth, + color: resolveColor(r.checkboxColor, '--tw-text-opacity'), + 'background-color': r.checkboxBackgroundColor, + 'border-color': resolveColor(r.checkboxBorderColor, '--tw-border-opacity'), + 'border-width': r.checkboxBorderWidth, + '--tw-shadow': r.checkboxTWShadow, }, }, { base: [`[type='checkbox']`], class: ['.form-checkbox'], styles: { - 'border-radius': borderRadius['none'], + 'border-radius': r.checkboxBorderRadius, }, }, { base: [`[type='radio']`], class: ['.form-radio'], styles: { - 'border-radius': '100%', + 'border-radius': r.radioBorderRadius, }, }, { base: [`[type='checkbox']:focus`, `[type='radio']:focus`], class: ['.form-checkbox:focus', '.form-radio:focus'], styles: { - outline: '2px solid transparent', - 'outline-offset': '2px', - '--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-ring-offset-width': '2px', - '--tw-ring-offset-color': '#fff', - '--tw-ring-color': resolveColor( - theme('colors.blue.600', colors.blue[600]), - '--tw-ring-opacity' - ), - '--tw-ring-offset-shadow': `var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)`, - '--tw-ring-shadow': `var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)`, - 'box-shadow': `var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)`, + outline: r.checkboxFocusOutline, + 'outline-offset': r.checkboxFocusOutlineOffset, + '--tw-ring-inset': r.checkboxFocusTwRingInset, + '--tw-ring-offset-width': r.checkboxFocusTwRingOffsetWidth, + '--tw-ring-offset-color': r.checkboxFocusTwRingOffsetColor, + '--tw-ring-color': resolveColor(r.checkboxFocusTwRingColor, '--tw-ring-opacity'), + '--tw-ring-offset-shadow': r.checkboxFocusTwRingOffsetShadow, + '--tw-ring-shadow': r.checkboxFocusTwRingShadow, + 'box-shadow': r.checkboxFocusBoxShadow, }, }, { base: [`[type='checkbox']:checked`, `[type='radio']:checked`], class: ['.form-checkbox:checked', '.form-radio:checked'], styles: { - 'border-color': `transparent`, - 'background-color': `currentColor`, - 'background-size': `100% 100%`, - 'background-position': `center`, - 'background-repeat': `no-repeat`, + 'border-color': r.checkboxCheckedBorderColor, + 'background-color': r.checkboxCheckedBackgroundColor, + 'background-size': r.checkboxCheckedBackgroundSize, + 'background-position': r.checkboxCheckedBackgroundPosition, + 'background-repeat': r.checkboxCheckedBackgroundRepeat, }, }, { base: [`[type='checkbox']:checked`], class: ['.form-checkbox:checked'], styles: { - 'background-image': `url("${svgToDataUri( - `` - )}")`, + 'background-image': r.checkboxCheckedBackgroundImage, }, }, { base: [`[type='radio']:checked`], class: ['.form-radio:checked'], styles: { - 'background-image': `url("${svgToDataUri( - `` - )}")`, + 'background-image': r.radioCheckedBackgroundImage, }, }, { @@ -276,8 +450,8 @@ const forms = plugin.withOptions(function (options = { strategy: undefined }) { '.form-radio:checked:focus', ], styles: { - 'border-color': 'transparent', - 'background-color': 'currentColor', + 'border-color': r.checkboxCheckedHoverBorderColor, + 'background-color': r.checkboxCheckedHoverBackgroundColor, }, }, { @@ -287,39 +461,39 @@ const forms = plugin.withOptions(function (options = { strategy: undefined }) { 'background-image': `url("${svgToDataUri( `` )}")`, - 'border-color': `transparent`, - 'background-color': `currentColor`, - 'background-size': `100% 100%`, - 'background-position': `center`, - 'background-repeat': `no-repeat`, + 'border-color': r.checkboxIndeterminateBorderColor, + 'background-color': r.checkboxIndeterminateBackgroundColor, + 'background-size': r.checkboxIndeterminateBackgroundSize, + 'background-position': r.checkboxIndeterminateBackgroundPosition, + 'background-repeat': r.checkboxIndeterminateBackgroundRepeat, }, }, { base: [`[type='checkbox']:indeterminate:hover`, `[type='checkbox']:indeterminate:focus`], class: ['.form-checkbox:indeterminate:hover', '.form-checkbox:indeterminate:focus'], styles: { - 'border-color': 'transparent', - 'background-color': 'currentColor', + 'border-color': r.checkboxIndeterminateHoverBorderColor, + 'background-color': r.checkboxIndeterminateHoverBackgroundColor, }, }, { base: [`[type='file']`], class: null, styles: { - background: 'unset', - 'border-color': 'inherit', - 'border-width': '0', - 'border-radius': '0', - padding: '0', - 'font-size': 'unset', - 'line-height': 'inherit', + background: r.fileBackground, + 'border-color': r.fileBorderColor, + 'border-width': r.fileBorderWidth, + 'border-radius': r.fileBorderRadius, + padding: r.filepadding, + 'font-size': r.fileFontSize, + 'line-height': r.fileLineHeight, }, }, { base: [`[type='file']:focus`], class: null, styles: { - outline: [`1px solid ButtonText`, `1px auto -webkit-focus-ring-color`], + outline: r.fileFocusOutline, }, }, ] diff --git a/tailwind.config.js b/tailwind.config.js index 5ef17d5..0e7469a 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,8 +1,14 @@ +const colors = require('tailwindcss/colors') + module.exports = { content: ['./index.html', './kitchen-sink.html'], theme: { extend: { - // + forms: ({ theme }) => ({ + baseTextColor: colors.amber[500], + baseBorderRadius: theme('borderRadius.xs'), + baseFocusBorderColor: theme('colors.yellow.500'), + }), }, }, plugins: [require('./src')],