npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

columns-resize

v0.1.7

Published

A tiny dependency-free library to create flex-based table-like layouts, which can be resized by user

Downloads

144

Readme

columns-resize

A tiny dependency-free library to create flex-based table-like layouts, which can be resized by user

Installation

npm

npm i columns-resize
import ColumnsResize from 'columns-resize'

CDN

<script src="https://unpkg.com/columns-resize@latest"></script>

Structure

The layout consists of rows (which must have display:flex style)

Rows contain columns that can be resized. When one column is resized, all columns with the same id are resized with it.

Columns contain some information and a resize handle that can be dragged to make adjustments to column size. Resize handles are optional: not all columns must have them, but if a resize handle is present, it must be nested within a column

Markup

This library relies on use of data-attributes.

Here's a list of data attributes that are important for us:

  • data-column-id="some-id" - this attribute must be present on every column in your layout. The id must be unique for each column
  • data-resize-handle - this attribute indicates elements that are used as handle bars which can be dragged to resize columns. Can be auto generated with autoResizeHandles option
  • data-no-auto-resize-handles - this optional data attribute can be used along with autoResizeHandles option to exclude rows from automatic handles generation
<!-- 
  row is the container of columns.
  each row must have display:flex
-->
<div class="row">
  <!--
    data-column-id must provide an id unique for each column
  -->
  <div class="column" data-column-id="name">
    Godric Gryffindor
    <!--
      data-resize-handle indicates the handlebar element,
      that can be dragged to resize columns.
      such element must be nested inside of the column element
    -->
    <div data-resize-handle></div>
  </div>
  
  <div class="column" data-column-id="faculty">
    Gryffindor
    <div data-resize-handle></div>
  </div>
  
  <div class="column" data-column-id="long-number">
    9847362594654783295483726543782
    <!--
      this is the last column in the row,
      so it doesn't have a resize handle
    -->
  </div>
  
</div>

Initialization

You need to provide the root element to limit the scope of each column set. This is the element from which the querySelector's fire, searching for all the data-attributed elements.

If you don't care about scope, or only have a single use case, feel free to provide document.body as root

const rootElement = document.getElementById('wrapper')

const columns = new ColumnsResize(rootElement)

Options

Along with the root element you can provide an options object

const columns = new ColumnsResize(rootElement, {
  defaultMinWidth: 50,
  minWidthByColumnId: {
    'name': 100
  },
  minWidthFormat: 'px',
  autoResizeHandles: true,
  onResizeStart: () => console.log('resize start'),
  onResizeEnd: () => console.log('resize end'),
  logs: true
})

options.defaultMinWidth

type: number

default: 50

A min width for each column unless a different min width is specified by minWidthByColumnId

The column will not shrink past its min width. If the user keeps resizing in the direction of a column that has reached its minimal width, the next column will start to shrink until there's no shrinkable columns left.

options.minWidthByColumnId

type: { [key: string]: number }

default: {}

Min widths for specific columns

options.minWidthFormat

type: 'px'|'0-1'

default: 'px'

Specifies the format of minWidthByColumnId. If set to 'px', min width values are treated as pixel sizes. If set to '0-1', a value from 0 to 1 is expected and min widths are calculated based on total columns width.

options.autoResizeHandles

type: boolean

default: false

Automatically create resize handles for every column (except the last one)

Note that positioning and styling of auto-generated handles is up to you (no styles are applied by default to the created elements)

If you need to exclude some rows from automatic resize handle generation, use data-no-auto-resize-handles on that row

<div class="row" data-no-auto-resize-handles>
  <!-- No resize handles in this row -->
  <div class="column" data-column-id="name">John</div>
  <div class="column" data-column-id="surname">Doe</div>
  <div class="column" data-column-id="age">28</div>
</div>
<div class="row">
  <div class="column" data-column-id="name">
    Mary
    <!-- Resize handle will be created here -->
  </div>
  <div class="column" data-column-id="surname">
    Perry
    <!-- And here -->
  </div>
  <div class="column" data-column-id="age">
    27
    <!-- But not here -->
  </div>
</div>

options.onResizeStart

type: () => void

default: undefined

Callback to be called when resize action is initiated

options.onResizeEnd

type: () => void

default: undefined

Callback to be called when resize action has ended

options.logs

type: boolean

default: false

Whether or not to print logs (could be useful for debugging)

Methods

reconnect()

If the DOM tree is updated - for example, new rows are added, you need to reconnect the instance

columns.reconnect()

disconnect()

If for any reason at some point you need to disable the resizability of your layout

columns.disconnect()

reset()

If at some point you need to reset column widths to their initial values

columns.reset()

Note that initial widths are measured at the initialization of instance and are not affected by disconnect / reconnect unless new columns are added (or removed). In that case, initial widths get overwritten

Classes

Conditional classes are applied to the key elements for styling purposes

See Live demo (with color coding enabled) for better understanding of how the classes are applied

Here's the list of classes and the elements they're applied to:

| Class name | Element(s) | Meaning | |---|---|---| | columns-resize-connected | Root, all columns, all handlebars | Instance is connected, columns resizable | | columns-resize-active | Root, columns currently being resized, handlebar currently being dragged | Resize action is happening right now, and this element is taking active part in it. You can expect exactly 1 handlebar and 2 columns to be active at any moment during every resize | | columns-resize-growing | Column currently growing | This column is active & its size is being increased | | columns-resize-shrinking | Column currently shrinking | This column is active & its size is being decreased |

Style Requirements & Recommendations

Rows

Every row must be a flexbox

.row {
  display: flex;
}

Columns

It is recommended for columns to have these two properties, however it depends on implementation

.column {
  text-overflow: ellipsis;
  white-space: nowrap;
}

Feel free to set the initial sizes of the columns with flex property

.column {
  flex: 1 1 33%;
}
.column:nth-child(2) {
  flex: 0 0 120px;
}

Note that evey element with data-column-id on it will automatically get these styles:

overflow: hidden;
box-sizing: border-box;

Resize Handles

Positioning and styling of the resize handles is up to you regardless of whether they're createdted automatically or marked up manually

It is recommended that each resize handle is positioned in the far-right part of the column, for example, like this:

[data-resize-handle] {
  position: absolute;
  right: 0;
  top: 0;
  height: 100%;
  width: 2px;
  cursor: col-resize;
}

You may find it useful to increase the size of the handle to make it more clickable, while keeping the line itself thinner for aesthetics. Then you'll need to get a bit tricky, but one possible solution is to style a line as an ::after element, while keeping the wider [data-resize-handle] element transparent:

[data-resize-handle] {
  width: 10px;
  display: flex;
  justify-content: center;
}
[data-resize-handle]::after {
  display: block;
  content: '';
  width: 2px;
  height: 100%;
  background: black;
}
[data-resize-handle].columns-resize-active::after {
  background: red;
}

Cursor

You may want to set cursor to grabbing (for example) on the entire page while the resize is in progress. This can be acheived by conditionally toggling a class on the body:

new ColumnsResize(rootElement, {
  onResizeStart() {
    document.body.classList.add('grabbing')
  },
  onResizeEnd() {
    document.body.classList.remove('grabbing')
  }
})
body.grabbing * {
  cursor: grabbing;
}