Compare commits

...
Author SHA1 Message Date
artem ash 8d0425bbbf minor 2024-02-15 07:25:06 -08:00
artem ash e28cd85934 sort of working 2024-02-14 22:50:18 -08:00
13 changed files with 214 additions and 75 deletions
@@ -48,15 +48,13 @@ const GridBlockComponent: React.FC<
}
else {
let defaultSet = false
for (const [key, value] of Object.entries(grid.at)) {
for (const [key, value] of Object.entries(grid.at as typeof grid.at)) {
if (!defaultSet) {
// ts brain fart!
clx += gridClx(value as GridColumnSpec)
clx += gridClx(value)
defaultSet = true
}
else {
// ts brain fart!
clx += gridClx(value as GridColumnSpec, `${key}:`)
clx += gridClx(value, `${key}:`)
}
}
}
+31 -14
View File
@@ -1,20 +1,15 @@
import React from 'react'
import Image from 'next/image'
import type { Dimensions } from '../../types'
import type { ImageBlock } from '../def'
import { constrain, containsToken, cn } from '../../util'
import { getConstaintsClx, containsToken, cn } from '../../util'
import type BlockComponentProps from './block-component-props'
const ImageBlockComponent: React.FC<BlockComponentProps & {
constraint?: Dimensions
}> = ({
const ImageBlockComponent: React.FC<BlockComponentProps> = ({
block,
className='',
agent,
constraint
agent
}) => {
if (block.blockType !== 'image') {
@@ -25,6 +20,7 @@ const ImageBlockComponent: React.FC<BlockComponentProps & {
src,
alt,
dim,
constraints,
props,
fullWidthOnMobile,
svgFillClass,
@@ -35,9 +31,8 @@ const ImageBlockComponent: React.FC<BlockComponentProps & {
const toSpread: any = {}
if (props?.fill === undefined) {
const dimCon = (constraint ? constrain(dim, constraint) : dim)
toSpread.width = dimCon.w
toSpread.height = dimCon.h
toSpread.width = dim.w
toSpread.height = dim.h
}
let _alt: string
@@ -52,6 +47,8 @@ const ImageBlockComponent: React.FC<BlockComponentProps & {
const _svgFillClass = svgFillClass ?? ''
let constraintsClx = ''
// TODO: use two elements with 'md:hidden' for 3/4 size
// https://nextjs.org/docs/app/building-your-application/optimizing/images#responsive
if (agent === 'phone' ) {
@@ -60,7 +57,6 @@ const ImageBlockComponent: React.FC<BlockComponentProps & {
style: {
width: '100%',
height: 'auto',
maxWidth: '420px'
},
sizes: '100vw',
}
@@ -74,6 +70,10 @@ const ImageBlockComponent: React.FC<BlockComponentProps & {
</div>
)
}
else if (constraints && ('xs' in constraints || 'w' in constraints)) {
constraintsClx = getConstaintsClx(constraints, 'xs')
}
// last stop-gap
else if (!specified('mobile-no-scale')) {
if (props?.style?.width === 'auto' && typeof props.style.height === 'number' ) {
props.style.height = props.style.height *.75
@@ -89,6 +89,11 @@ const ImageBlockComponent: React.FC<BlockComponentProps & {
}
}
}
else {
constraintsClx = getConstaintsClx(constraints)
}
const stopGapClx = constraintsClx ? 'mx-auto ' : ''
const right = containsToken(specifiers, 'right')
const center = containsToken(specifiers, 'center')
@@ -97,10 +102,22 @@ const ImageBlockComponent: React.FC<BlockComponentProps & {
return (props?.fill) ? (
<div className='relative w-full h-full'>
<Image src={src} alt={_alt} {...toSpread} {...props} className={cn(_svgFillClass, 'max-w-[70vw] mx-auto', className)}/>
<Image
src={src}
alt={_alt}
{...toSpread}
{...props}
className={cn(_svgFillClass, stopGapClx, constraintsClx, className)}
/>
</div>
) : (
<Image src={src} alt={_alt} {...toSpread} {...props} className={cn(alignSelfClx, _svgFillClass, 'max-w-[70vw] mx-auto', className)}/>
<Image
src={src}
alt={_alt}
{...toSpread}
{...props}
className={cn(alignSelfClx, _svgFillClass, stopGapClx, constraintsClx, className)}
/>
)
}
@@ -48,7 +48,7 @@ const ScreenfulComponent: React.FC<{
narrowGutters ?
'px-6 lg:px-8 2xl:px-2 pb-6 pt-15 md:pt-26 lg:pt-28 '
:
'px-[8vw] xl:px-[1vw] pb-[8vh] pt-[calc(44px+4vh)] md:pt-[calc(80px+6vh)] ',
'px-[8vw] xl:px-[1vw] pb-[8vh] pt-[calc(44px+3vh)] md:pt-[calc(80px+6vh)] ',
(agent && agent !== 'desktop') ? 'pt-15 sm:pt-17 pb-0 px-3 sm:px-8' : ''
]
@@ -41,9 +41,8 @@ const SpaceBlockComponent: React.FC<BlockComponentProps> = ({
ldMerge(_sizes, SPACE_DEFAULTS, b.sizes)
let clx = ''
for (const [key, value] of Object.entries(_sizes)) {
// ts brain fart!
clx += `${key}:h-${value as TWSpaceUnit} `
for (const [key, value] of Object.entries(_sizes as typeof _sizes)) {
clx += `${key}:h-${value} `
}
if (b.test) {
+6 -1
View File
@@ -22,7 +22,12 @@ interface ImageBlock extends Block, ImageDef {
sizes?: string
/** if true, any alignement specifiers are ignored */
fill?: boolean
style?: any
style?: {
objectFit?: string
objectPosition?: string
width?: number | string
height?: number | string
}
}
}
+56 -2
View File
@@ -1,4 +1,24 @@
// https://tailwindcss.com/docs/content-configuration#dynamic-class-names
import screenDef from './screens.tailwind'
const screens = Object.keys(screenDef)
const fulls = () => {
const r = []
r.push('w-full')
r.push('max-w-full')
r.push('h-full')
r.push('max-h-full')
screens.forEach((sc) => {
r.push(`${sc}:w-full`)
r.push(`${sc}:max-w-full`)
r.push(`${sc}:h-full`)
r.push(`${sc}:max-h-full`)
})
return r
}
// https://tailwindcss.com/docs/content-configuration#dynamic-class-names
// https://tailwindcss.com/docs/content-configuration#safelisting-classes
export default [
@@ -7,7 +27,7 @@ export default [
pattern: /grid-cols-[1-6]/,
variants: [ 'xs', 'sm', 'md', 'lg', 'xl', '2xl' ]
},
{ // SpaceBlock
{ // SpaceBlock h-1 through h-40
pattern: /h-([0-9]|[1-3][0-9]|40)/,
variants: [ 'xs', 'sm', 'md', 'lg', 'xl', '2xl' ]
},
@@ -17,6 +37,40 @@ export default [
{ // EnhHeadingBlock
pattern: /mb-([1-9]|1[0-2])/
},
// util/index: getConstraintClx() w-1 --> w-256, and h-1 --> h-256
// util/index: getConstraintClx() w-[1%] --> w-[100%] and h-[1%] --> h-[100%]
// https://github.com/tailwindlabs/tailwindcss/discussions/7908
...[...Array(256).keys()].flatMap((i) => {
const r = []
r.push(`max-w-${i}`)
r.push(`max-h-${i}`)
screens.forEach((sc) => {
r.push(`${sc}:max-w-${i}`)
r.push(`${sc}:max-h-${i}`)
})
return r
}),
...[...Array(99).keys()].flatMap((i) => {
const r = []
r.push(`max-w-[${i}%]`)
r.push(`max-h-[${i}%]`)
screens.forEach((sc) => {
r.push(`${sc}:max-w-[${i}%]`)
r.push(`${sc}:max-h-[${i}%]`)
})
return r
}),
...fulls(),
/*
{ // util/index: getConstraintClx() w-1 --> w-256, and h-1 --> h-256
pattern: /(w|h)-([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-6])/
},
{
// util/index: getConstraintClx() w-[1%] --> w-[256]
pattern: /(w|h)-\[([1-9]|[1-9][0-9]|100)%\]/
},
*/
'md:text-left', // EnhHeadingBlock
'md:text-center',
'md:text-right',
+26 -48
View File
@@ -1,4 +1,14 @@
export default {
/*
if rem = 16px
256 tw units is enough to specify up to
1024px in 4px (0.25rem) increments.
If one needs more than that, one can
use screen sizes to define constraints.
eg, 'max-w-screen-lg'
*/
const MAX = 256
const sp = {
px: '1px',
0: '0px',
0.5: '0.125rem',
@@ -7,51 +17,19 @@ export default {
2: '0.5rem',
2.5: '0.625rem',
3: '0.75rem',
3.5: '0.875rem',
4: '1rem',
5: '1.25rem',
6: '1.5rem',
7: '1.75rem',
8: '2rem',
9: '2.25rem',
10: '2.5rem',
11: '2.75rem',
12: '3rem',
13: '3.25rem',
14: '3.5rem',
15: '3.75rem',
16: '4rem',
17: '4.25rem',
18: '4.5rem',
19: '4.75rem',
20: '5rem',
21: '5.25rem',
22: '5.5rem',
23: '5.75rem',
24: '6rem',
25: '5.25rem',
26: '5.5rem',
27: '5.75rem',
28: '7rem',
29: '7.25rem',
30: '7.5rem',
31: '7.75rem',
32: '8rem',
33: '8.25rem',
34: '8.5rem',
35: '8.75rem',
36: '9rem',
37: '9.25rem',
38: '9.5rem',
39: '9.75rem',
40: '10rem',
44: '11rem',
48: '12rem',
52: '13rem',
56: '14rem',
60: '15rem',
64: '16rem',
72: '18rem',
80: '20rem',
96: '24rem',
3.5: '0.875rem'
}
for (let i = 4; i <= MAX; i++) {
const twoPlaces = Math.round(((i * 0.25) + Number.EPSILON) * 100) / 100
if (Number.isSafeInteger(twoPlaces)) {
sp[i] = `${Math.round(twoPlaces)}rem`
}
else {
sp[i] = `${parseFloat(twoPlaces).toFixed(2)}rem`
}
}
export default sp
@@ -9,6 +9,8 @@ import spacing from './spacing.tailwind'
import { fontFamily, fontSize} from './fonts.tailwind'
import typographyPlugin from './typo-plugin'
export default {
presets: [],
darkMode: ["class"],
@@ -589,6 +591,7 @@ export default {
fit: 'fit-content',
},
maxWidth: ({ theme, breakpoints }) => ({
...spacing,
none: 'none',
0: '0rem',
xs: '20rem',
+1
View File
@@ -3,6 +3,7 @@
"include": [
"**/*.ts",
"**/*.tsx",
"**/*.js" // Conf files etc.
],
"exclude": [
"node_modules",
+28
View File
@@ -0,0 +1,28 @@
import type { Breakpoint } from './breakpoints'
type Constraint = {
w: number | `${number}%` | 'auto'
h: number | `${number}%` | 'auto'
}
/**
* All values are in tw spacing units
*
*
* NOTE: If applying in one dimension because other
* is auto in style, ImageBlockComp applies this with style={}
* so it has higher precidence than tw classes. Otherwise,
* tw classes will be used.
*/
type ResponsiveConstraints = {
[key in (Breakpoint)]?: Constraint
}
type Constraints = Constraint | ResponsiveConstraints
export {
type Constraint,
type ResponsiveConstraints,
type Constraints
}
+4
View File
@@ -1,3 +1,4 @@
import type { Constraints } from './constraints'
import type { Dimensions } from './dimensions'
/**
@@ -21,6 +22,9 @@ interface ImageDef {
* can determine the aspect ratio
*/
dim: Dimensions
/** See Constraints */
constraints?: Constraints
}
export {
+1
View File
@@ -10,6 +10,7 @@ export { COMMON_GRID_2_COL, COMMON_GRID_3_COL } from './grid-def'
export type {default as GridDef, GridColumnSpec} from './grid-def'
export type { TShirtDimensions, Dimensions } from './dimensions'
export type { ContactInfo, ContactInfoFields } from './contact-info'
export type { Constraint, Constraints, ResponsiveConstraints } from './constraints'
import type BulletItem from './bullet-item'
import type Icon from './icon'
+52 -1
View File
@@ -2,7 +2,7 @@ import { compiler as mdCompiler } from 'markdown-to-jsx'
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
import type { Dimensions } from '../types'
import type { Dimensions, Breakpoint, Constraints, Constraint, ResponsiveConstraints } from '../types'
// @ts-ignore
import _merge from 'lodash.merge'
@@ -51,6 +51,7 @@ export const asNum = (n: number | `${number}`): number => (
)
// https://stackoverflow.com/questions/3971841/how-to-resize-images-proportionally-keeping-the-aspect-ratio
/** deprecated */
export const constrain = (dim: Dimensions, constraint: Dimensions): Dimensions => {
const c = {
w: asNum(constraint.w),
@@ -68,6 +69,56 @@ export const constrain = (dim: Dimensions, constraint: Dimensions): Dimensions =
}
}
const _getConstraintClx = (con: Constraint, prefix?: string) => {
let clxArray: string[] = []
if (typeof con.w === 'number') {
clxArray.push(`max-w-${con.w}`)
}
else if (con.w === 'auto') {
clxArray.push('max-w-auto')
}
else { // percentage
clxArray.push(con.w === '100%' ? 'max-w-full' : `max-w-[${con.w as string}]`)
}
if (typeof con.h === 'number') {
clxArray.push(`max-h-${con.w}`)
}
else if (con.h === 'auto') {
clxArray.push('max-h-auto')
}
else { // percentage
clxArray.push(con.h === '100%' ? 'max-w-full' : `max-h-[${con.h as string}]`)
}
const _clxArray = (prefix) ? clxArray.map((t: string) => (prefix + t)) : clxArray
return _clxArray.join(' ')
}
export const getConstaintsClx = (
con: Constraints | undefined,
bp?: Breakpoint
): string => {
if (!con) return ''
// single value
if ('w' in con) {
return _getConstraintClx(con as Constraint)
}
if (bp && bp in con) {
return _getConstraintClx(con[bp] as Constraint)
}
let clxArray: string[] = []
for (const [key, value] of Object.entries(con as ResponsiveConstraints)) {
clxArray.push(_getConstraintClx(value, `${key}:`))
}
return clxArray.join(' ')
}
export const containsToken = (s: string | undefined, toFind: string): boolean => (s ? s.split(' ').includes(toFind) : false)
export const ldMerge = (